tyrion-cli 0.1.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.
Files changed (73) hide show
  1. tyrion_cli-0.1.0/.gitignore +17 -0
  2. tyrion_cli-0.1.0/LICENSE +21 -0
  3. tyrion_cli-0.1.0/PKG-INFO +247 -0
  4. tyrion_cli-0.1.0/README.md +217 -0
  5. tyrion_cli-0.1.0/pyproject.toml +74 -0
  6. tyrion_cli-0.1.0/src/tyrion_agent/__init__.py +0 -0
  7. tyrion_cli-0.1.0/src/tyrion_agent/events.py +89 -0
  8. tyrion_cli-0.1.0/src/tyrion_agent/harness.py +273 -0
  9. tyrion_cli-0.1.0/src/tyrion_agent/loop.py +273 -0
  10. tyrion_cli-0.1.0/src/tyrion_agent/messages.py +119 -0
  11. tyrion_cli-0.1.0/src/tyrion_agent/provider.py +32 -0
  12. tyrion_cli-0.1.0/src/tyrion_agent/provider_events.py +70 -0
  13. tyrion_cli-0.1.0/src/tyrion_agent/py.typed +0 -0
  14. tyrion_cli-0.1.0/src/tyrion_agent/sessions/__init__.py +28 -0
  15. tyrion_cli-0.1.0/src/tyrion_agent/sessions/entries.py +68 -0
  16. tyrion_cli-0.1.0/src/tyrion_agent/sessions/jsonl.py +67 -0
  17. tyrion_cli-0.1.0/src/tyrion_agent/sessions/tree.py +132 -0
  18. tyrion_cli-0.1.0/src/tyrion_agent/tool_history.py +59 -0
  19. tyrion_cli-0.1.0/src/tyrion_agent/tools.py +84 -0
  20. tyrion_cli-0.1.0/src/tyrion_agent/types.py +7 -0
  21. tyrion_cli-0.1.0/src/tyrion_ai/__init__.py +0 -0
  22. tyrion_cli-0.1.0/src/tyrion_ai/env.py +38 -0
  23. tyrion_cli-0.1.0/src/tyrion_ai/fake.py +50 -0
  24. tyrion_cli-0.1.0/src/tyrion_ai/http.py +21 -0
  25. tyrion_cli-0.1.0/src/tyrion_ai/model_limits.py +152 -0
  26. tyrion_cli-0.1.0/src/tyrion_ai/openai_compatible.py +432 -0
  27. tyrion_cli-0.1.0/src/tyrion_ai/py.typed +0 -0
  28. tyrion_cli-0.1.0/src/tyrion_coding/__init__.py +0 -0
  29. tyrion_cli-0.1.0/src/tyrion_coding/cli.py +166 -0
  30. tyrion_cli-0.1.0/src/tyrion_coding/commands.py +173 -0
  31. tyrion_cli-0.1.0/src/tyrion_coding/context_window.py +104 -0
  32. tyrion_cli-0.1.0/src/tyrion_coding/data/__init__.py +0 -0
  33. tyrion_cli-0.1.0/src/tyrion_coding/data/system_prompt.md +19 -0
  34. tyrion_cli-0.1.0/src/tyrion_coding/display.py +106 -0
  35. tyrion_cli-0.1.0/src/tyrion_coding/prompt_templates.py +41 -0
  36. tyrion_cli-0.1.0/src/tyrion_coding/provider_catalog.py +76 -0
  37. tyrion_cli-0.1.0/src/tyrion_coding/provider_config.py +161 -0
  38. tyrion_cli-0.1.0/src/tyrion_coding/py.typed +0 -0
  39. tyrion_cli-0.1.0/src/tyrion_coding/rendering.py +86 -0
  40. tyrion_cli-0.1.0/src/tyrion_coding/resources.py +36 -0
  41. tyrion_cli-0.1.0/src/tyrion_coding/session.py +258 -0
  42. tyrion_cli-0.1.0/src/tyrion_coding/session_coding.py +107 -0
  43. tyrion_cli-0.1.0/src/tyrion_coding/skills.py +71 -0
  44. tyrion_cli-0.1.0/src/tyrion_coding/system_prompt.py +42 -0
  45. tyrion_cli-0.1.0/src/tyrion_coding/theme.py +128 -0
  46. tyrion_cli-0.1.0/src/tyrion_coding/tools.py +529 -0
  47. tyrion_cli-0.1.0/src/tyrion_coding/tui/__init__.py +6 -0
  48. tyrion_cli-0.1.0/src/tyrion_coding/tui/app.py +411 -0
  49. tyrion_cli-0.1.0/src/tyrion_coding/tui/connect_modal.py +158 -0
  50. tyrion_cli-0.1.0/src/tyrion_coding/tui/picker.py +150 -0
  51. tyrion_cli-0.1.0/src/tyrion_coding/tui/styles.py +222 -0
  52. tyrion_cli-0.1.0/src/tyrion_coding/tui/welcome.py +89 -0
  53. tyrion_cli-0.1.0/src/tyrion_coding/tui/widgets.py +474 -0
  54. tyrion_cli-0.1.0/tests/conftest.py +42 -0
  55. tyrion_cli-0.1.0/tests/test_cli.py +31 -0
  56. tyrion_cli-0.1.0/tests/test_coding_session.py +83 -0
  57. tyrion_cli-0.1.0/tests/test_command_menu.py +372 -0
  58. tyrion_cli-0.1.0/tests/test_compaction.py +176 -0
  59. tyrion_cli-0.1.0/tests/test_context_window.py +133 -0
  60. tyrion_cli-0.1.0/tests/test_credentials.py +55 -0
  61. tyrion_cli-0.1.0/tests/test_display.py +136 -0
  62. tyrion_cli-0.1.0/tests/test_loop.py +99 -0
  63. tyrion_cli-0.1.0/tests/test_model_limits.py +149 -0
  64. tyrion_cli-0.1.0/tests/test_openai_provider.py +338 -0
  65. tyrion_cli-0.1.0/tests/test_packaging.py +353 -0
  66. tyrion_cli-0.1.0/tests/test_rendering.py +124 -0
  67. tyrion_cli-0.1.0/tests/test_session.py +65 -0
  68. tyrion_cli-0.1.0/tests/test_session_titles.py +207 -0
  69. tyrion_cli-0.1.0/tests/test_system_prompt.py +37 -0
  70. tyrion_cli-0.1.0/tests/test_theme.py +115 -0
  71. tyrion_cli-0.1.0/tests/test_tools.py +55 -0
  72. tyrion_cli-0.1.0/tests/test_tui_dialogs.py +292 -0
  73. tyrion_cli-0.1.0/tests/test_tui_widgets.py +398 -0
@@ -0,0 +1,17 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Tool caches
13
+ .pytest_cache/
14
+ .ruff_cache/
15
+
16
+ # macOS
17
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Tejasveer Singh Sodhi
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,247 @@
1
+ Metadata-Version: 2.5
2
+ Name: tyrion-cli
3
+ Version: 0.1.0
4
+ Summary: A terminal-native AI coding agent: streaming TUI, tool use, resumable sessions, and any OpenAI-compatible model.
5
+ Project-URL: Homepage, https://github.com/Xtejasveer/tyrion
6
+ Project-URL: Repository, https://github.com/Xtejasveer/tyrion
7
+ Project-URL: Issues, https://github.com/Xtejasveer/tyrion/issues
8
+ Author: Tejasveer Singh Sodhi
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: ai,cli,coding-agent,llm,terminal,textual,tui
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: MacOS
16
+ Classifier: Operating System :: POSIX :: Linux
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development
21
+ Requires-Python: >=3.12
22
+ Requires-Dist: anyio>=4.0
23
+ Requires-Dist: httpx>=0.27
24
+ Requires-Dist: pydantic>=2.11
25
+ Requires-Dist: pygments>=2.18
26
+ Requires-Dist: rich>=13.0
27
+ Requires-Dist: textual>=8.0
28
+ Requires-Dist: typer>=0.12
29
+ Description-Content-Type: text/markdown
30
+
31
+ # ⚔️ Tyrion — Terminal-Native AI Coding Agent
32
+
33
+ <div align="center">
34
+
35
+ ![Tyrion Terminal](https://raw.githubusercontent.com/Xtejasveer/tyrion/main/assets/welcome.png)
36
+
37
+ *A powerful, transparent, and responsive AI coding companion built directly for your terminal.*
38
+
39
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/)
40
+ [![Textual](https://img.shields.io/badge/built%20with-Textual-teal.svg)](https://textual.textualize.io/)
41
+ [![Tests: 200 passed](https://img.shields.io/badge/tests-200%20passed-success.svg)](#testing)
42
+ [![Architecture: Pi-derived](https://img.shields.io/badge/architecture-Pi--derived-gold.svg)](#architecture)
43
+
44
+ </div>
45
+
46
+ ---
47
+
48
+ ## 📦 Install
49
+
50
+ Works on **macOS and Linux**. On Windows, use [WSL](https://learn.microsoft.com/windows/wsl/install).
51
+
52
+ ```bash
53
+ curl -LsSf https://raw.githubusercontent.com/Xtejasveer/tyrion/main/install.sh | sh && exec "$SHELL" -l
54
+ ```
55
+
56
+ Then just run `tyrion`. The `&& exec "$SHELL" -l` at the end restarts your shell so `tyrion` works right away in this same terminal window. (In scripts and CI, leave that part off: there is no shell to restart.) The script installs [`uv`](https://docs.astral.sh/uv/) if you don't have it, then installs Tyrion into its own isolated environment. You don't need Python installed (uv fetches Python 3.12 for you), and it never uses `sudo`. Want to read it first? [`install.sh`](install.sh) is short.
57
+
58
+ - **Update:** run the install command again.
59
+ - **Uninstall:** `uv tool uninstall tyrion-cli` (your chats and settings in `~/.tyrion` are left alone; delete that folder to remove them too).
60
+ - **`command not found: tyrion`?** The terminal window you installed from can't see the new command yet (this happens if the command was run without the `&& exec "$SHELL" -l` part). Run `exec "$SHELL" -l`, or open a new terminal window, or run `export PATH="$HOME/.local/bin:$PATH"` and try again. The installer prints these for you at the end.
61
+
62
+ ---
63
+
64
+ ## 📖 Overview
65
+
66
+ **Tyrion** is an autonomous terminal-native coding agent designed to pair-program with you directly inside your command line. Whether you are exploring an unfamiliar codebase, refactoring complex modules, fixing bugs, or writing unit tests, Tyrion provides a fluid, distraction-free environment that operates on your local workspace.
67
+
68
+ Equipped with filesystem tools, terminal execution capabilities, automatic token compaction, and in-UI provider switching, Tyrion pairs deep reasoning with responsive terminal aesthetics.
69
+
70
+ ---
71
+
72
+ ## 🏛️ Architecture
73
+
74
+ Tyrion's core engine architecture is derived from the **Pi coding agent architecture** developed by Mario Zechner (BadLogic Games). It adheres strictly to modular separation of concerns, separating pure stateless execution from stateful orchestration and persistence.
75
+
76
+ ```
77
+ ┌─────────────────────────────────────────────────────────────┐
78
+ │ Presentation Layer │
79
+ │ Textual TUI (app.py) │ Print CLI (cli.py / rendering)│
80
+ ├─────────────────────────────────────────────────────────────┤
81
+ │ Coding Domain Layer │
82
+ │ CodingSession │ Coding Tools (read, write, edit, bash) │
83
+ │ System Prompt Builder │ Compaction & Token Accounting │
84
+ ├─────────────────────────────────────────────────────────────┤
85
+ │ Agent Harness Layer │
86
+ │ AgentHarness (Stateful brain, cancellation, events) │
87
+ │ Session Persistence (Append-only JSONL Tree) │
88
+ ├─────────────────────────────────────────────────────────────┤
89
+ │ Pure Agent Loop Layer │
90
+ │ run_agent_loop (Stateless generator, turn manager) │
91
+ ├─────────────────────────────────────────────────────────────┤
92
+ │ Model Provider Layer │
93
+ │ OpenAI-Compatible Streaming Provider (OpenRouter, etc.) │
94
+ └─────────────────────────────────────────────────────────────┘
95
+ ```
96
+
97
+ ### Key Architectural Layers
98
+
99
+ 1. **Pure Agent Loop (`src/tyrion_agent/loop.py`)**:
100
+ - A completely **stateless generator** driving model-to-tool feedback cycles.
101
+ - Emits fine-grained events (`AgentStartEvent`, `TurnStartEvent`, `MessageUpdateEvent`, `ToolExecutionStartEvent`, `ToolExecutionEndEvent`, `TurnEndEvent`, `AgentEndEvent`).
102
+ - Knows nothing about disk persistence or frontends; simply consumes an immutable transcript and yields execution events.
103
+
104
+ 2. **Agent Harness (`src/tyrion_agent/harness.py`)**:
105
+ - The stateful supervisor that wraps the pure loop.
106
+ - Manages message history, handles cooperative cancellation, dispatches events to listeners, and auto-repairs interrupted tool calls.
107
+
108
+ 3. **Append-Only Tree Session Storage (`src/tyrion_agent/sessions/`)**:
109
+ - Conversations are persisted to append-only JSONL logs on disk.
110
+ - Sessions are structured as trees rather than linear lists, enabling branching, time-travel, and lossless restoration via `reconstruct_state()`.
111
+
112
+ 4. **Model Provider Abstraction (`src/tyrion_ai/`)**:
113
+ - High-performance, streaming SSE client supporting OpenAI, OpenRouter, DeepSeek, and local LLMs (Ollama, vLLM).
114
+ - Captures real server-side token usage (`stream_options: {"include_usage": True}`) and features self-healing retries if a provider rejects usage flags.
115
+ - Configurable context window limits and local override support via `~/.tyrion/model_limits.json`.
116
+
117
+ 5. **Coding Domain & Tools (`src/tyrion_coding/`)**:
118
+ - `CodingSession`: Coordinates the project workspace, loads project guidelines (`AGENTS.md` / instructions), and automatically assembles system prompts.
119
+ - Real-time token compaction: Summarizes older conversation history using the model when nearing the 80% context window ceiling.
120
+
121
+ ---
122
+
123
+ ## 🎯 Use Cases
124
+
125
+ - **Codebase Exploration & Analysis**: Ask Tyrion to inspect directories, summarize module relationships, and trace function call graphs across unfamiliar repositories.
126
+ - **Hands-Off Multi-File Refactoring**: Prompt Tyrion to migrate legacy patterns or update dependencies; it reads targets, formulates plans, edits files, and verifies changes.
127
+ - **Bug Diagnosis & TDD**: Feed Tyrion a failing test suite or trace error; it will isolate the defect, apply precise edits, and re-run pytest until all tests are green.
128
+ - **Remote & SSH Pair Programming**: Full-featured interactive TUI that runs in headless servers, Docker containers, and SSH sessions without requiring a browser or Electron.
129
+
130
+ ---
131
+
132
+ ## ✨ Features
133
+
134
+ - 🎨 **Lannister Brand Theme**: Warm ink-black surfaces (`#0e0d10`, `#16151a`), rich Lannister gold (`#e0b04f`), crimson accents, and custom Pygments syntax highlighting designed for chat readability.
135
+ - ⌨️ **Interactive Slash Command Palette**: Type `/` anywhere in the prompt to open an instant auto-completing command menu with arrow-key navigation and keyboard shortcuts.
136
+ - ⚡ **Full Tool Arsenal**:
137
+ - `read`: Reads files with line number indexing and byte caps.
138
+ - `write`: Creates or replaces files safely.
139
+ - `edit`: Precise substring replacements with uniqueness validation.
140
+ - `bash`: Subprocess execution with process group termination (`os.killpg`) to eliminate orphan background processes.
141
+ - 🔌 **In-UI Connection (`/connect`)**: Connect your OpenRouter or OpenAI API keys directly within the app and have them saved in `~/.tyrion/credentials.json` (readable only by you).
142
+ - 📊 **Real-Time Token Usage Bar**: Dynamic status bar with visual block gauges (`▰▰▰▱▱▱`) displaying exact server-reported token usage against context limits.
143
+ - 🧹 **Automatic & Manual Compaction (`/compact`)**: Compresses long conversations into persistent summaries, preserving immediate context while keeping token usage lean.
144
+ - 🗂️ **Session Resuming (`/resume`)**: Visual session picker overlay allowing you to jump between past conversations and pick up right where you left off.
145
+
146
+ ---
147
+
148
+ ## 🛡️ Safety
149
+
150
+ Tyrion is early software (v0.1). Read this before pointing it at a project you care about:
151
+
152
+ - **It runs commands and edits files without asking.** The `bash`, `write` and `edit` tools act immediately and can reach any path your user can. Use it inside a git repository so you can review and undo changes (`git diff`, `git restore`).
153
+ - **Your code leaves your machine.** Your prompts and the files Tyrion reads are sent to the model provider you connect.
154
+ - **Your API key is stored in plain text** in `~/.tyrion/credentials.json`, readable only by you (permissions `600`). Prefer a key with a spending limit.
155
+ - **Files can carry instructions.** In an untrusted repository, a malicious file could try to steer the model into running commands.
156
+
157
+ ---
158
+
159
+ ## 🚀 Getting Started
160
+
161
+ > Just want to use Tyrion? See [Install](#-install) above. This section is for running it from source.
162
+
163
+ ### Prerequisites
164
+
165
+ - Python 3.12+
166
+ - [`uv`](https://github.com/astral-sh/uv) (recommended) or `pip`
167
+
168
+ ### Installation from source
169
+
170
+ Clone the repository and install dependencies:
171
+
172
+ ```bash
173
+ git clone https://github.com/Xtejasveer/tyrion.git
174
+ cd tyrion
175
+ uv sync
176
+ ```
177
+
178
+ ### Running Tyrion
179
+
180
+ Launch the interactive Terminal User Interface:
181
+
182
+ ```bash
183
+ uv run tyrion
184
+ ```
185
+
186
+ *Tip: On first launch, run `/connect` to select your model provider (e.g. OpenRouter) and enter your API key.*
187
+
188
+ ### Command-Line Usage
189
+
190
+ Tyrion also supports quick one-shot command-line runs:
191
+
192
+ ```bash
193
+ # Ask a direct question
194
+ uv run tyrion "Explain how the routing works in src/api.py"
195
+
196
+ # Specify a model
197
+ uv run tyrion --model google/gemini-2.5-flash "Write unit tests for tools.py"
198
+
199
+ # Resume an existing session by ID
200
+ uv run tyrion --resume <session_id>
201
+
202
+ # Include a file's contents in the prompt
203
+ uv run tyrion "What is causing this traceback? $(cat error.log)"
204
+
205
+ # Or pipe the whole prompt in
206
+ cat prompt.txt | uv run tyrion
207
+ ```
208
+
209
+ ---
210
+
211
+ ## 🕹️ Slash Commands Reference
212
+
213
+ | Command | Description |
214
+ | :--- | :--- |
215
+ | `/connect` | Open provider dialog to enter & persist your API key |
216
+ | `/model <name>` | Hot-swap active LLM model on the fly |
217
+ | `/resume` | Open visual session picker modal to switch conversations |
218
+ | `/compact` | Manually compress and summarize older conversation history |
219
+ | `/clear` | Wipe current transcript and return to centered landing screen |
220
+ | `/help` | List all available slash commands and descriptions |
221
+ | `/quit` / `/exit` | Gracefully exit the application |
222
+
223
+ ---
224
+
225
+ ## 🧪 Testing
226
+
227
+ Tyrion comes with a comprehensive test suite covering the agent loop, bash tool process isolation, SSE streaming, model limits, context compaction, TUI dialogs, command menu navigation, and theme rendering:
228
+
229
+ ```bash
230
+ uv run pytest
231
+ ```
232
+
233
+ ```
234
+ ============================= 200 passed in 17.28s =============================
235
+ ```
236
+
237
+ ---
238
+
239
+ ## 🤝 Acknowledgements
240
+
241
+ Tyrion's core architecture and design principles are derived from the **Pi coding agent architecture** designed by [Mario Zechner](https://github.com/badlogic) ([BadLogic Games](https://badlogicgames.com/)). We extend our gratitude to Mario for the clean conceptual framework of separating the pure stateless agent loop from stateful harnesses and persistent session trees.
242
+
243
+ ---
244
+
245
+ ## 📜 License
246
+
247
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,217 @@
1
+ # ⚔️ Tyrion — Terminal-Native AI Coding Agent
2
+
3
+ <div align="center">
4
+
5
+ ![Tyrion Terminal](https://raw.githubusercontent.com/Xtejasveer/tyrion/main/assets/welcome.png)
6
+
7
+ *A powerful, transparent, and responsive AI coding companion built directly for your terminal.*
8
+
9
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/)
10
+ [![Textual](https://img.shields.io/badge/built%20with-Textual-teal.svg)](https://textual.textualize.io/)
11
+ [![Tests: 200 passed](https://img.shields.io/badge/tests-200%20passed-success.svg)](#testing)
12
+ [![Architecture: Pi-derived](https://img.shields.io/badge/architecture-Pi--derived-gold.svg)](#architecture)
13
+
14
+ </div>
15
+
16
+ ---
17
+
18
+ ## 📦 Install
19
+
20
+ Works on **macOS and Linux**. On Windows, use [WSL](https://learn.microsoft.com/windows/wsl/install).
21
+
22
+ ```bash
23
+ curl -LsSf https://raw.githubusercontent.com/Xtejasveer/tyrion/main/install.sh | sh && exec "$SHELL" -l
24
+ ```
25
+
26
+ Then just run `tyrion`. The `&& exec "$SHELL" -l` at the end restarts your shell so `tyrion` works right away in this same terminal window. (In scripts and CI, leave that part off: there is no shell to restart.) The script installs [`uv`](https://docs.astral.sh/uv/) if you don't have it, then installs Tyrion into its own isolated environment. You don't need Python installed (uv fetches Python 3.12 for you), and it never uses `sudo`. Want to read it first? [`install.sh`](install.sh) is short.
27
+
28
+ - **Update:** run the install command again.
29
+ - **Uninstall:** `uv tool uninstall tyrion-cli` (your chats and settings in `~/.tyrion` are left alone; delete that folder to remove them too).
30
+ - **`command not found: tyrion`?** The terminal window you installed from can't see the new command yet (this happens if the command was run without the `&& exec "$SHELL" -l` part). Run `exec "$SHELL" -l`, or open a new terminal window, or run `export PATH="$HOME/.local/bin:$PATH"` and try again. The installer prints these for you at the end.
31
+
32
+ ---
33
+
34
+ ## 📖 Overview
35
+
36
+ **Tyrion** is an autonomous terminal-native coding agent designed to pair-program with you directly inside your command line. Whether you are exploring an unfamiliar codebase, refactoring complex modules, fixing bugs, or writing unit tests, Tyrion provides a fluid, distraction-free environment that operates on your local workspace.
37
+
38
+ Equipped with filesystem tools, terminal execution capabilities, automatic token compaction, and in-UI provider switching, Tyrion pairs deep reasoning with responsive terminal aesthetics.
39
+
40
+ ---
41
+
42
+ ## 🏛️ Architecture
43
+
44
+ Tyrion's core engine architecture is derived from the **Pi coding agent architecture** developed by Mario Zechner (BadLogic Games). It adheres strictly to modular separation of concerns, separating pure stateless execution from stateful orchestration and persistence.
45
+
46
+ ```
47
+ ┌─────────────────────────────────────────────────────────────┐
48
+ │ Presentation Layer │
49
+ │ Textual TUI (app.py) │ Print CLI (cli.py / rendering)│
50
+ ├─────────────────────────────────────────────────────────────┤
51
+ │ Coding Domain Layer │
52
+ │ CodingSession │ Coding Tools (read, write, edit, bash) │
53
+ │ System Prompt Builder │ Compaction & Token Accounting │
54
+ ├─────────────────────────────────────────────────────────────┤
55
+ │ Agent Harness Layer │
56
+ │ AgentHarness (Stateful brain, cancellation, events) │
57
+ │ Session Persistence (Append-only JSONL Tree) │
58
+ ├─────────────────────────────────────────────────────────────┤
59
+ │ Pure Agent Loop Layer │
60
+ │ run_agent_loop (Stateless generator, turn manager) │
61
+ ├─────────────────────────────────────────────────────────────┤
62
+ │ Model Provider Layer │
63
+ │ OpenAI-Compatible Streaming Provider (OpenRouter, etc.) │
64
+ └─────────────────────────────────────────────────────────────┘
65
+ ```
66
+
67
+ ### Key Architectural Layers
68
+
69
+ 1. **Pure Agent Loop (`src/tyrion_agent/loop.py`)**:
70
+ - A completely **stateless generator** driving model-to-tool feedback cycles.
71
+ - Emits fine-grained events (`AgentStartEvent`, `TurnStartEvent`, `MessageUpdateEvent`, `ToolExecutionStartEvent`, `ToolExecutionEndEvent`, `TurnEndEvent`, `AgentEndEvent`).
72
+ - Knows nothing about disk persistence or frontends; simply consumes an immutable transcript and yields execution events.
73
+
74
+ 2. **Agent Harness (`src/tyrion_agent/harness.py`)**:
75
+ - The stateful supervisor that wraps the pure loop.
76
+ - Manages message history, handles cooperative cancellation, dispatches events to listeners, and auto-repairs interrupted tool calls.
77
+
78
+ 3. **Append-Only Tree Session Storage (`src/tyrion_agent/sessions/`)**:
79
+ - Conversations are persisted to append-only JSONL logs on disk.
80
+ - Sessions are structured as trees rather than linear lists, enabling branching, time-travel, and lossless restoration via `reconstruct_state()`.
81
+
82
+ 4. **Model Provider Abstraction (`src/tyrion_ai/`)**:
83
+ - High-performance, streaming SSE client supporting OpenAI, OpenRouter, DeepSeek, and local LLMs (Ollama, vLLM).
84
+ - Captures real server-side token usage (`stream_options: {"include_usage": True}`) and features self-healing retries if a provider rejects usage flags.
85
+ - Configurable context window limits and local override support via `~/.tyrion/model_limits.json`.
86
+
87
+ 5. **Coding Domain & Tools (`src/tyrion_coding/`)**:
88
+ - `CodingSession`: Coordinates the project workspace, loads project guidelines (`AGENTS.md` / instructions), and automatically assembles system prompts.
89
+ - Real-time token compaction: Summarizes older conversation history using the model when nearing the 80% context window ceiling.
90
+
91
+ ---
92
+
93
+ ## 🎯 Use Cases
94
+
95
+ - **Codebase Exploration & Analysis**: Ask Tyrion to inspect directories, summarize module relationships, and trace function call graphs across unfamiliar repositories.
96
+ - **Hands-Off Multi-File Refactoring**: Prompt Tyrion to migrate legacy patterns or update dependencies; it reads targets, formulates plans, edits files, and verifies changes.
97
+ - **Bug Diagnosis & TDD**: Feed Tyrion a failing test suite or trace error; it will isolate the defect, apply precise edits, and re-run pytest until all tests are green.
98
+ - **Remote & SSH Pair Programming**: Full-featured interactive TUI that runs in headless servers, Docker containers, and SSH sessions without requiring a browser or Electron.
99
+
100
+ ---
101
+
102
+ ## ✨ Features
103
+
104
+ - 🎨 **Lannister Brand Theme**: Warm ink-black surfaces (`#0e0d10`, `#16151a`), rich Lannister gold (`#e0b04f`), crimson accents, and custom Pygments syntax highlighting designed for chat readability.
105
+ - ⌨️ **Interactive Slash Command Palette**: Type `/` anywhere in the prompt to open an instant auto-completing command menu with arrow-key navigation and keyboard shortcuts.
106
+ - ⚡ **Full Tool Arsenal**:
107
+ - `read`: Reads files with line number indexing and byte caps.
108
+ - `write`: Creates or replaces files safely.
109
+ - `edit`: Precise substring replacements with uniqueness validation.
110
+ - `bash`: Subprocess execution with process group termination (`os.killpg`) to eliminate orphan background processes.
111
+ - 🔌 **In-UI Connection (`/connect`)**: Connect your OpenRouter or OpenAI API keys directly within the app and have them saved in `~/.tyrion/credentials.json` (readable only by you).
112
+ - 📊 **Real-Time Token Usage Bar**: Dynamic status bar with visual block gauges (`▰▰▰▱▱▱`) displaying exact server-reported token usage against context limits.
113
+ - 🧹 **Automatic & Manual Compaction (`/compact`)**: Compresses long conversations into persistent summaries, preserving immediate context while keeping token usage lean.
114
+ - 🗂️ **Session Resuming (`/resume`)**: Visual session picker overlay allowing you to jump between past conversations and pick up right where you left off.
115
+
116
+ ---
117
+
118
+ ## 🛡️ Safety
119
+
120
+ Tyrion is early software (v0.1). Read this before pointing it at a project you care about:
121
+
122
+ - **It runs commands and edits files without asking.** The `bash`, `write` and `edit` tools act immediately and can reach any path your user can. Use it inside a git repository so you can review and undo changes (`git diff`, `git restore`).
123
+ - **Your code leaves your machine.** Your prompts and the files Tyrion reads are sent to the model provider you connect.
124
+ - **Your API key is stored in plain text** in `~/.tyrion/credentials.json`, readable only by you (permissions `600`). Prefer a key with a spending limit.
125
+ - **Files can carry instructions.** In an untrusted repository, a malicious file could try to steer the model into running commands.
126
+
127
+ ---
128
+
129
+ ## 🚀 Getting Started
130
+
131
+ > Just want to use Tyrion? See [Install](#-install) above. This section is for running it from source.
132
+
133
+ ### Prerequisites
134
+
135
+ - Python 3.12+
136
+ - [`uv`](https://github.com/astral-sh/uv) (recommended) or `pip`
137
+
138
+ ### Installation from source
139
+
140
+ Clone the repository and install dependencies:
141
+
142
+ ```bash
143
+ git clone https://github.com/Xtejasveer/tyrion.git
144
+ cd tyrion
145
+ uv sync
146
+ ```
147
+
148
+ ### Running Tyrion
149
+
150
+ Launch the interactive Terminal User Interface:
151
+
152
+ ```bash
153
+ uv run tyrion
154
+ ```
155
+
156
+ *Tip: On first launch, run `/connect` to select your model provider (e.g. OpenRouter) and enter your API key.*
157
+
158
+ ### Command-Line Usage
159
+
160
+ Tyrion also supports quick one-shot command-line runs:
161
+
162
+ ```bash
163
+ # Ask a direct question
164
+ uv run tyrion "Explain how the routing works in src/api.py"
165
+
166
+ # Specify a model
167
+ uv run tyrion --model google/gemini-2.5-flash "Write unit tests for tools.py"
168
+
169
+ # Resume an existing session by ID
170
+ uv run tyrion --resume <session_id>
171
+
172
+ # Include a file's contents in the prompt
173
+ uv run tyrion "What is causing this traceback? $(cat error.log)"
174
+
175
+ # Or pipe the whole prompt in
176
+ cat prompt.txt | uv run tyrion
177
+ ```
178
+
179
+ ---
180
+
181
+ ## 🕹️ Slash Commands Reference
182
+
183
+ | Command | Description |
184
+ | :--- | :--- |
185
+ | `/connect` | Open provider dialog to enter & persist your API key |
186
+ | `/model <name>` | Hot-swap active LLM model on the fly |
187
+ | `/resume` | Open visual session picker modal to switch conversations |
188
+ | `/compact` | Manually compress and summarize older conversation history |
189
+ | `/clear` | Wipe current transcript and return to centered landing screen |
190
+ | `/help` | List all available slash commands and descriptions |
191
+ | `/quit` / `/exit` | Gracefully exit the application |
192
+
193
+ ---
194
+
195
+ ## 🧪 Testing
196
+
197
+ Tyrion comes with a comprehensive test suite covering the agent loop, bash tool process isolation, SSE streaming, model limits, context compaction, TUI dialogs, command menu navigation, and theme rendering:
198
+
199
+ ```bash
200
+ uv run pytest
201
+ ```
202
+
203
+ ```
204
+ ============================= 200 passed in 17.28s =============================
205
+ ```
206
+
207
+ ---
208
+
209
+ ## 🤝 Acknowledgements
210
+
211
+ Tyrion's core architecture and design principles are derived from the **Pi coding agent architecture** designed by [Mario Zechner](https://github.com/badlogic) ([BadLogic Games](https://badlogicgames.com/)). We extend our gratitude to Mario for the clean conceptual framework of separating the pure stateless agent loop from stateful harnesses and persistent session trees.
212
+
213
+ ---
214
+
215
+ ## 📜 License
216
+
217
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,74 @@
1
+ [build-system]
2
+ requires = ["hatchling>=1.27"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ # "tyrion" is already taken on PyPI, so the package is published as "tyrion-cli".
7
+ # The command you type is still `tyrion` (see [project.scripts]).
8
+ name = "tyrion-cli"
9
+ version = "0.1.0"
10
+ description = "A terminal-native AI coding agent: streaming TUI, tool use, resumable sessions, and any OpenAI-compatible model."
11
+ readme = "README.md"
12
+ requires-python = ">=3.12"
13
+ license = "MIT"
14
+ license-files = ["LICENSE"]
15
+ authors = [{ name = "Tejasveer Singh Sodhi" }]
16
+ keywords = ["ai", "coding-agent", "llm", "cli", "tui", "terminal", "textual"]
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Environment :: Console",
20
+ "Intended Audience :: Developers",
21
+ "Operating System :: MacOS",
22
+ "Operating System :: POSIX :: Linux",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Programming Language :: Python :: 3.13",
26
+ "Topic :: Software Development",
27
+ ]
28
+ dependencies = [
29
+ "anyio>=4.0",
30
+ "httpx>=0.27",
31
+ "pydantic>=2.11",
32
+ "pygments>=2.18",
33
+ "rich>=13.0",
34
+ "textual>=8.0",
35
+ "typer>=0.12",
36
+ ]
37
+
38
+ [project.urls]
39
+ Homepage = "https://github.com/Xtejasveer/tyrion"
40
+ Repository = "https://github.com/Xtejasveer/tyrion"
41
+ Issues = "https://github.com/Xtejasveer/tyrion/issues"
42
+
43
+ [project.scripts]
44
+ tyrion = "tyrion_coding.cli:app"
45
+
46
+ # Development tools live here, not in the runtime dependencies, so a normal
47
+ # install does not pull in pytest and ruff. `uv sync` installs this group.
48
+ [dependency-groups]
49
+ dev = [
50
+ "pytest>=8.0",
51
+ "pytest-asyncio>=1.4.0",
52
+ "ruff>=0.5",
53
+ ]
54
+
55
+ [tool.hatch.build.targets.wheel]
56
+ packages = ["src/tyrion_ai", "src/tyrion_agent", "src/tyrion_coding"]
57
+
58
+ [tool.hatch.build.targets.wheel.force-include]
59
+ "src/tyrion_coding/data/system_prompt.md" = "tyrion_coding/data/system_prompt.md"
60
+
61
+ # Ship only what belongs in a source release (no scratch scripts, screenshots, or caches).
62
+ [tool.hatch.build.targets.sdist]
63
+ include = ["/src", "/tests", "/README.md", "/LICENSE", "/pyproject.toml"]
64
+
65
+ [tool.pytest.ini_options]
66
+ asyncio_mode = "auto"
67
+
68
+ # Pin the lint rules to real-bug checks (pyflakes + syntax) so CI does not change
69
+ # behaviour whenever ruff changes its defaults.
70
+ [tool.ruff]
71
+ target-version = "py312"
72
+
73
+ [tool.ruff.lint]
74
+ select = ["E4", "E7", "E9", "F"]
File without changes
@@ -0,0 +1,89 @@
1
+ """Events emitted by the portable agent layer."""
2
+
3
+ from __future__ import annotations
4
+ from typing import Annotated, Literal
5
+
6
+ from pydantic import Field
7
+
8
+ from tyrion_agent.messages import AgentMessage, ToolResultMessage, WireModel
9
+ from tyrion_agent.provider_events import AssistantMessageEvent
10
+ from tyrion_agent.tools import AgentToolResult
11
+ from tyrion_agent.types import JSONValue
12
+
13
+ class AgentStartEvent(WireModel):
14
+ """The agent has started processing."""
15
+ type: Literal["agent_start"] = "agent_start"
16
+
17
+ class AgentEndEvent(WireModel):
18
+ """The agent has finished processing."""
19
+
20
+ type: Literal["agent_end"] = "agent_end"
21
+ messages: list[AgentMessage] = Field(default_factory=list)
22
+
23
+ class TurnStartEvent(WireModel):
24
+ """A new model turn has started."""
25
+
26
+ type: Literal["turn_start"] = "turn_start"
27
+
28
+ class TurnEndEvent(WireModel):
29
+ """A model turn has completed."""
30
+
31
+ type: Literal["turn_end"] = "turn_end"
32
+ message: AgentMessage
33
+ tool_results: list[ToolResultMessage] = Field(default_factory=list)
34
+
35
+ class MessageStartEvent(WireModel):
36
+ """A message has started (user, assistant or tool result)."""
37
+ type: Literal["message_start"] = "message_start"
38
+ message: AgentMessage
39
+
40
+ class MessageUpdateEvent(WireModel):
41
+ """A streaming delta has arrived for the current message."""
42
+
43
+ type: Literal["message_update"] = "message_update"
44
+ message: AgentMessage
45
+ assistant_message_event: AssistantMessageEvent
46
+
47
+ class MessageEndEvent(WireModel):
48
+ """A message has been finalized."""
49
+ type: Literal["message_end"] = "message_end"
50
+ message: AgentMessage
51
+
52
+ class ToolExecutionStartEvent(WireModel):
53
+ """A tool has started executing."""
54
+
55
+ type: Literal["tool_execution_start"] = "tool_execution_start"
56
+ tool_call_id: str
57
+ tool_name : str
58
+ args: dict[str, JSONValue] = Field(default_factory=dict)
59
+
60
+ class ToolExecutionUpdateEvent(WireModel):
61
+ """A tool has started executing."""
62
+
63
+ type: Literal["tool_execution_update"] = "tool_execution_update"
64
+ tool_call_id: str
65
+ tool_name : str
66
+ args: dict[str, JSONValue] = Field(default_factory=dict)
67
+ partial_result: AgentToolResult
68
+
69
+ class ToolExecutionEndEvent(WireModel):
70
+ """A tool has finished executing."""
71
+ type: Literal["tool_execution_end"] = "tool_execution_end"
72
+ tool_call_id: str
73
+ tool_name: str
74
+ result: AgentToolResult
75
+ is_error: bool
76
+ # Union of all agent events
77
+ type AgentEvent = Annotated[
78
+ AgentStartEvent
79
+ | AgentEndEvent
80
+ | TurnStartEvent
81
+ | TurnEndEvent
82
+ | MessageStartEvent
83
+ | MessageUpdateEvent
84
+ | MessageEndEvent
85
+ | ToolExecutionStartEvent
86
+ | ToolExecutionUpdateEvent
87
+ | ToolExecutionEndEvent,
88
+ Field(discriminator="type"),
89
+ ]