gentui 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.
gentui-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gentui contributors
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.
gentui-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,293 @@
1
+ Metadata-Version: 2.4
2
+ Name: gentui
3
+ Version: 0.1.0
4
+ Summary: A terminal interface for prototyping agents really quickly, for any AG-UI backend
5
+ Keywords: ag-ui,agents,ai-agents,tui,terminal,textual,llm,human-in-the-loop,strands,agentcore
6
+ Author: rahrajlat
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Topic :: Software Development
16
+ Classifier: Topic :: Terminals
17
+ Requires-Dist: ag-ui-protocol>=1.0.0
18
+ Requires-Dist: httpx>=0.28.1
19
+ Requires-Dist: jsonpatch>=1.33
20
+ Requires-Dist: textual>=8.2.8
21
+ Requires-Dist: textual-plotext>=1.0.1
22
+ Requires-Dist: boto3>=1.40 ; extra == 'agentcore'
23
+ Requires-Python: >=3.12
24
+ Project-URL: Homepage, https://github.com/rahrajlat/Gentui
25
+ Project-URL: Repository, https://github.com/rahrajlat/Gentui
26
+ Project-URL: Documentation, https://github.com/rahrajlat/Gentui#readme
27
+ Project-URL: Issues, https://github.com/rahrajlat/Gentui/issues
28
+ Project-URL: Changelog, https://github.com/rahrajlat/Gentui/blob/main/CHANGELOG.md
29
+ Provides-Extra: agentcore
30
+ Description-Content-Type: text/markdown
31
+
32
+ <div align="center">
33
+
34
+ <img src="https://raw.githubusercontent.com/rahrajlat/Gentui/main/docs/assets/hero.gif" alt="Gentui: generative UI for your terminal" width="640">
35
+
36
+ **A terminal interface for prototyping agents really quickly.**<br>
37
+ Point it at any [AG-UI](https://docs.ag-ui.com) backend and get streaming chat, the model's chain of thought,<br>
38
+ tables, charts and human approval, with no frontend to build.
39
+
40
+ [![CI](https://img.shields.io/github/actions/workflow/status/rahrajlat/Gentui/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/rahrajlat/Gentui/actions/workflows/ci.yml)
41
+ [![Python](https://img.shields.io/badge/python-3.12%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org)
42
+ [![Textual](https://img.shields.io/badge/built%20with-Textual-4FD6C8?style=flat-square)](https://textual.textualize.io)
43
+ [![AG-UI](https://img.shields.io/badge/protocol-AG--UI-A78BFA?style=flat-square)](https://docs.ag-ui.com)
44
+ [![Tested with Strands Agents](https://img.shields.io/badge/tested%20with-Strands%20Agents%20(AWS)-FF9900?style=flat-square)](https://strandsagents.com)
45
+ [![uv](https://img.shields.io/badge/packaged%20with-uv-DE5FE9?style=flat-square)](https://docs.astral.sh/uv/)
46
+ [![License: MIT](https://img.shields.io/badge/license-MIT-7BD88F?style=flat-square)](https://github.com/rahrajlat/Gentui/blob/main/LICENSE)
47
+ [![Status](https://img.shields.io/badge/status-alpha-F2C46D?style=flat-square)](#status)
48
+ [![PRs welcome](https://img.shields.io/badge/PRs-welcome-7BD88F?style=flat-square)](#contributing)
49
+ [![Stars](https://img.shields.io/github/stars/rahrajlat/Gentui?style=flat-square&color=4FD6C8)](https://github.com/rahrajlat/Gentui/stargazers)
50
+ [![Last commit](https://img.shields.io/github/last-commit/rahrajlat/Gentui?style=flat-square&color=A78BFA)](https://github.com/rahrajlat/Gentui/commits/main)
51
+
52
+ </div>
53
+
54
+ ---
55
+
56
+ ## Why Gentui?
57
+
58
+ **Gentui is a terminal interface for prototyping agents really quickly.**
59
+
60
+ While developing agents locally, we end up spending our time on the frontend: a Streamlit or Chainlit
61
+ app, or a React project, just to talk to the agent. Each one is a separate frontend to build and keep
62
+ running, and it slows down the thing you actually want to iterate on: the agent.
63
+
64
+ Gentui removes that step. Install it, point it at your agent's AG-UI endpoint, and you get a chat, the
65
+ model's **chain of thought**, **human-in-the-loop (HITL)** and **approval** flows out of the box, with no
66
+ frontend code to write. Change your agent, restart it, and you're prototyping again in seconds.
67
+
68
+ When the agent calls a tool, the **tool call becomes the UI**: a command to approve, a table, a chart,
69
+ a live plan. Nothing risky runs until you click **Approve**.
70
+
71
+ **Tested with the [Strands Agents](https://strandsagents.com) framework (AWS's open-source agent SDK) over
72
+ AG-UI**: both on a custom backend (the [example backend](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend)) and on the official
73
+ [`ag-ui-strands`](https://pypi.org/project/ag-ui-strands/) adapter.
74
+
75
+ <div align="center">
76
+ <img src="https://raw.githubusercontent.com/rahrajlat/Gentui/main/docs/assets/demo.gif" alt="Gentui demo: ask, review the proposed command, approve, see the output, chart it" width="860">
77
+ </div>
78
+
79
+ ## Features
80
+
81
+ - **Works with any AG-UI backend.** Streaming text, tool calls and shared state work out of the box;
82
+ unknown tools show as a readable card, never an error.
83
+ - **Chain of thought, visible.** Reasoning streams into a collapsible "Thought for 3s" block.
84
+ - **Human-in-the-loop approval** built on AG-UI **interrupts**: the run ends waiting, your click
85
+ `resume`s it. The model can't approve its own commands.
86
+ - **Generative widgets from tool calls:** command card, command output, tables, terminal charts
87
+ (line, bar, scatter, histogram), live plan checklist.
88
+ - **Developer-friendly:** an event inspector (`d`) showing the raw SSE payloads exactly as sent, `/theme`,
89
+ `/clear`, `/reasoning`, and a clear [backend contract](https://github.com/rahrajlat/Gentui/blob/main/docs/tool-contract.md).
90
+ - **Yours to customise:** TOML config, hot-reloaded CSS, your own themes, and Python plugins that add
91
+ widgets, slash commands and event hooks.
92
+ - **Runs agents on AWS too:** invoke agents hosted on Amazon Bedrock AgentCore Runtime (AG-UI protocol) via boto3.
93
+ - **Backend-agnostic by design.** The client has no framework code; a complete example backend lives in
94
+ [`examples/strands-backend`](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend).
95
+
96
+ ## The sample agent: natural language → shell
97
+
98
+ The demo above is the bundled example backend, a **natural-language-to-shell agent** built on Strands
99
+ Agents. You describe a task in plain English, it proposes a single shell command, and **nothing runs
100
+ until you approve it**.
101
+
102
+ 1. **Ask:** "what are the 5 largest files here?"
103
+ 2. **Review:** a shell sub-agent writes one command for your shell (bash, or PowerShell on Windows)
104
+ with a one-line explanation and a risk level: `safe`, `caution` or `dangerous`.
105
+ 3. **Decide:** **Approve**, **Edit** the command first, or **Reject**. Your decision is sent back as an
106
+ AG-UI `resume`; the model can't approve for itself or change the command.
107
+ 4. **Run:** only the approved command executes, with a timeout, an output cap and a fixed working
108
+ directory. A denylist (recursive delete of root or home, disk formatting, shutdown, fork bombs,
109
+ interactive programs) is checked at proposal, at approval and again right before running. It is a
110
+ safety net, not a sandbox.
111
+
112
+ The same agent can also show results as a **table** or **chart**, lay out multi-step work as a live
113
+ **plan**, explain what a command does (an explainer sub-agent), and keep **long-term memory** between
114
+ conversations. It's a worked example of the [backend contract](https://github.com/rahrajlat/Gentui/blob/main/docs/tool-contract.md): copy it, or add your
115
+ own tools with [this guide](https://github.com/rahrajlat/Gentui/blob/main/examples/strands-backend/docs/add_a_tool.md).
116
+
117
+ ## Quick start
118
+
119
+ Requires [uv](https://docs.astral.sh/uv/) and Python 3.12.
120
+
121
+ ```bash
122
+ git clone https://github.com/rahrajlat/Gentui.git && cd Gentui
123
+ uv sync
124
+ uv run gentui http://localhost:8000/agent # your AG-UI endpoint
125
+ ```
126
+
127
+ No backend yet? Run the [sample natural-language-to-shell agent](#the-sample-agent-natural-language--shell)
128
+ (Strands Agents + FastAPI) in another terminal. It uses a local
129
+ [Ollama](https://ollama.com) by default; see its [README](https://github.com/rahrajlat/Gentui/blob/main/examples/strands-backend/README.md) for other providers:
130
+
131
+ ```bash
132
+ cd examples/strands-backend
133
+ uv sync && cp .env.example .env
134
+ uv run server # http://localhost:8000/agent
135
+ ```
136
+
137
+ ```bash
138
+ uv run gentui https://my.host/agent --token sk-... # bearer auth
139
+ uv run gentui URL -H "X-Org: acme" --theme nord --dev # extra header, theme, event inspector
140
+ ```
141
+
142
+ | Key / command | Does |
143
+ |---|---|
144
+ | `Enter` | send |
145
+ | `d` or `Ctrl+D` | toggle the event inspector |
146
+ | `Ctrl+Q` | quit |
147
+ | `/help` `/theme <name>` `/clear` `/reasoning` `/dev` `/quit` | slash commands |
148
+
149
+ ## Agents on Amazon Bedrock AgentCore Runtime
150
+
151
+ Gentui can also invoke an agent hosted on **[AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html)**
152
+ with boto3's `invoke_agent_runtime`, using your normal AWS credentials. The runtime must be deployed with the
153
+ **AG-UI protocol**.
154
+
155
+ ```bash
156
+ uv sync --extra agentcore # boto3 is an optional extra
157
+ uv run gentui arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my_agent-AbCdEfGhIj
158
+ uv run gentui ARN --profile dev --region eu-west-1 # optional: AWS profile and region
159
+ uv run gentui ARN --qualifier prod # optional: a specific runtime endpoint
160
+ ```
161
+
162
+ `--profile` and `--region` are both **optional**. Without them, Gentui uses the standard AWS credential chain
163
+ (`AWS_PROFILE`, SSO, environment variables) and the region in the ARN. They can also be set in `gentui.toml` as
164
+ `aws_profile` and `region`.
165
+
166
+ One conversation is one runtime session, errors come with fixes (missing credentials, denied access, wrong ARN), and
167
+ busy sessions are retried. Details, IAM permissions and troubleshooting: **[docs/agentcore.md](https://github.com/rahrajlat/Gentui/blob/main/docs/agentcore.md)**.
168
+ Both a runtime ARN and an endpoint ARN (`.../runtime-endpoint/DEFAULT`) work.
169
+
170
+ ## Configure
171
+
172
+ Put options in `./gentui.toml` or `~/.config/gentui/config.toml`. Flags, `GENTUI_URL` and
173
+ `GENTUI_TOKEN` override the file. Every option is documented in
174
+ [`gentui.example.toml`](https://github.com/rahrajlat/Gentui/blob/main/gentui.example.toml): backend URL, token and headers, props sent with every run,
175
+ title, welcome text, theme, splash and logo, reasoning on/off, timestamps, plugins and widget mapping.
176
+
177
+ > **Stateless backends** (ones that rebuild context from the message list, like the official
178
+ > `ag-ui-strands` adapter) need `send_history = true`. By default only the newest message is sent and
179
+ > the backend is expected to keep history per `threadId`.
180
+
181
+ ## Customise
182
+
183
+ - **Theme:** `theme = "nord"` or `/theme <name>`. The default is `gentui` (teal and violet); `claude`
184
+ (coral) is also built in.
185
+ - **Your own styling:** `css = "my.tcss"` loads a [Textual CSS](https://textual.textualize.io/guide/CSS/)
186
+ file on top of the defaults and **hot-reloads while the app runs**. Useful selectors: `.user`,
187
+ `.assistant`, `.thinking`, `.error`, `ToolWidget`, `#chat`, `#prompt`.
188
+ - **Your own widget for a backend tool:** subclass `ToolWidget`, then map it without any plugin file:
189
+
190
+ ```toml
191
+ [widgets]
192
+ show_map = "my_widgets:MapWidget"
193
+ ```
194
+
195
+ ## Plugins
196
+
197
+ A plugin is a plain Python file. Drop it in `./gentui_plugins/` or `~/.config/gentui/plugins/`, list it in
198
+ `plugins = [...]` or `--plugin`, or ship it as a pip package using the `gentui.plugins` entry point.
199
+
200
+ ```python
201
+ from gentui.plugins import on_event, register_command
202
+ from gentui.tui.widgets.base import ToolWidget
203
+ from gentui.tui.widgets.registry import register_widget
204
+
205
+ @register_widget("weather") # render tool calls named "weather"
206
+ class Weather(ToolWidget):
207
+ def on_end(self, args): self.show(f"☀ {args['city']}")
208
+
209
+ @register_command("ping", "say pong") # adds /ping
210
+ def ping(app, args): app.notify("pong")
211
+
212
+ @on_event("TOOL_CALL_RESULT") # hook any AG-UI event
213
+ async def audit(app, event): ...
214
+
215
+ def setup(app): ... # optional, runs once the app is mounted
216
+ ```
217
+
218
+ Plugins can mount any Textual widget into the conversation with `await app.mount_chat(widget)`. A
219
+ broken plugin is reported in a toast and never stops the app.
220
+
221
+ ## Build a backend for it
222
+
223
+ Any language works: serve a `POST` endpoint that streams AG-UI events. To get the rich widgets, name
224
+ your tools like this (anything else shows a JSON card). The full contract, including the approval
225
+ flow and a checklist, is in **[docs/tool-contract.md](https://github.com/rahrajlat/Gentui/blob/main/docs/tool-contract.md)**.
226
+
227
+ | Tool name | Arguments / result | Renders |
228
+ |---|---|---|
229
+ | `propose_command` | `{command, explanation, risk: safe\|caution\|dangerous}` | command card with Approve / Edit / Reject; the decision goes back as an AG-UI `resume` of the run's interrupt |
230
+ | `run_command` | result JSON `{command, exit_code, timed_out, truncated, output}` | output card |
231
+ | `show_table` | `{title, columns, rows}` | table |
232
+ | `show_chart` | `{type: line\|bar\|scatter\|histogram, title, x, series: [{name, values}], x_label, y_label, bins}` | terminal chart (plotext) |
233
+ | `search_memory` | `{query}` | quiet "◌ recalled …" line |
234
+ | `todo_write` + state `plan` | state `{"plan": [{content, status}]}` | live checklist |
235
+
236
+ ## How it works
237
+
238
+ ```
239
+ gentui (Textual) ── POST /agent (RunAgentInput) ──▶ any AG-UI backend
240
+ ▲ │
241
+ │◀────────────── SSE: AG-UI events ─────────────────┘
242
+
243
+ Approve ▸ `resume` of the run's interrupt ──▶ backend runs the approved command
244
+ ```
245
+
246
+ | Piece | File |
247
+ |---|---|
248
+ | SSE client (RunAgentInput in, typed events out) | [`tui/agui_client.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/agui_client.py) |
249
+ | Event → widget dispatch, interrupts, chat | [`tui/app.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/app.py) |
250
+ | Widgets and the tool-name registry | [`tui/widgets/`](https://github.com/rahrajlat/Gentui/tree/main/src/gentui/tui/widgets) |
251
+ | Logo, splash and animation | [`tui/branding.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/branding.py), [`tui/splash.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/splash.py) |
252
+ | Plugin API and config | [`plugins.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/plugins.py), [`config.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/config.py) |
253
+
254
+ AG-UI events used: `RUN_STARTED/FINISHED/ERROR` (with `outcome: interrupt`), `TEXT_MESSAGE_*`,
255
+ `REASONING_*`, `TOOL_CALL_START/ARGS/END/RESULT`, `STATE_SNAPSHOT`, `STATE_DELTA`. The request side
256
+ uses `messages`, `forwardedProps` and `resume`.
257
+
258
+ ## Status
259
+
260
+ Gentui is **alpha**. What has been verified, and what has not:
261
+
262
+ - Built and tested against the **Strands Agents** framework (AWS) over AG-UI: the
263
+ [example backend](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend) and the official
264
+ [`ag-ui-strands`](https://pypi.org/project/ag-ui-strands/) adapter (with `send_history = true`).
265
+ - AgentCore Runtime support works against a real runtime (confirmed by the author with a plain runtime ARN) and only
266
+ covers runtimes using the AG-UI protocol. Other setups are covered by tests with a fake boto3 client and botocore's `Stubber`.
267
+ - Backends on other frameworks, the interrupt flow against a backend other than the example, other model
268
+ providers than Ollama, and native Windows are **untested**.
269
+ - The look relies on Unicode box-drawing and block characters. If glyphs are missing, try a terminal
270
+ font such as DejaVu Sans Mono, Cascadia or JetBrains Mono.
271
+
272
+ **Ideas, not built yet:** `show_form` / `ask_approval` tools, a composable JSON-tree UI tool, persistent
273
+ threads, a `--demo` mode and record/replay of runs.
274
+
275
+ ## Development
276
+
277
+ ```bash
278
+ uv run pytest -q # TUI tests: headless, no LLM or backend needed
279
+ cd examples/strands-backend && uv run pytest -q # the example backend's own tests
280
+ ```
281
+
282
+ The images above are generated from the app's own code:
283
+ `uv run --with pillow python docs/assets/build_assets.py`.
284
+
285
+ ## Contributing
286
+
287
+ Issues and pull requests are welcome. Please run both test suites before opening a PR, and add a test
288
+ with any behaviour change. Because Gentui is a client for an open protocol, changes that keep it
289
+ backend-agnostic are the easiest to accept.
290
+
291
+ ## License
292
+
293
+ [MIT](https://github.com/rahrajlat/Gentui/blob/main/LICENSE). Free to use, modify and distribute, including the [example backend](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend).
gentui-0.1.0/README.md ADDED
@@ -0,0 +1,262 @@
1
+ <div align="center">
2
+
3
+ <img src="https://raw.githubusercontent.com/rahrajlat/Gentui/main/docs/assets/hero.gif" alt="Gentui: generative UI for your terminal" width="640">
4
+
5
+ **A terminal interface for prototyping agents really quickly.**<br>
6
+ Point it at any [AG-UI](https://docs.ag-ui.com) backend and get streaming chat, the model's chain of thought,<br>
7
+ tables, charts and human approval, with no frontend to build.
8
+
9
+ [![CI](https://img.shields.io/github/actions/workflow/status/rahrajlat/Gentui/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/rahrajlat/Gentui/actions/workflows/ci.yml)
10
+ [![Python](https://img.shields.io/badge/python-3.12%2B-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org)
11
+ [![Textual](https://img.shields.io/badge/built%20with-Textual-4FD6C8?style=flat-square)](https://textual.textualize.io)
12
+ [![AG-UI](https://img.shields.io/badge/protocol-AG--UI-A78BFA?style=flat-square)](https://docs.ag-ui.com)
13
+ [![Tested with Strands Agents](https://img.shields.io/badge/tested%20with-Strands%20Agents%20(AWS)-FF9900?style=flat-square)](https://strandsagents.com)
14
+ [![uv](https://img.shields.io/badge/packaged%20with-uv-DE5FE9?style=flat-square)](https://docs.astral.sh/uv/)
15
+ [![License: MIT](https://img.shields.io/badge/license-MIT-7BD88F?style=flat-square)](https://github.com/rahrajlat/Gentui/blob/main/LICENSE)
16
+ [![Status](https://img.shields.io/badge/status-alpha-F2C46D?style=flat-square)](#status)
17
+ [![PRs welcome](https://img.shields.io/badge/PRs-welcome-7BD88F?style=flat-square)](#contributing)
18
+ [![Stars](https://img.shields.io/github/stars/rahrajlat/Gentui?style=flat-square&color=4FD6C8)](https://github.com/rahrajlat/Gentui/stargazers)
19
+ [![Last commit](https://img.shields.io/github/last-commit/rahrajlat/Gentui?style=flat-square&color=A78BFA)](https://github.com/rahrajlat/Gentui/commits/main)
20
+
21
+ </div>
22
+
23
+ ---
24
+
25
+ ## Why Gentui?
26
+
27
+ **Gentui is a terminal interface for prototyping agents really quickly.**
28
+
29
+ While developing agents locally, we end up spending our time on the frontend: a Streamlit or Chainlit
30
+ app, or a React project, just to talk to the agent. Each one is a separate frontend to build and keep
31
+ running, and it slows down the thing you actually want to iterate on: the agent.
32
+
33
+ Gentui removes that step. Install it, point it at your agent's AG-UI endpoint, and you get a chat, the
34
+ model's **chain of thought**, **human-in-the-loop (HITL)** and **approval** flows out of the box, with no
35
+ frontend code to write. Change your agent, restart it, and you're prototyping again in seconds.
36
+
37
+ When the agent calls a tool, the **tool call becomes the UI**: a command to approve, a table, a chart,
38
+ a live plan. Nothing risky runs until you click **Approve**.
39
+
40
+ **Tested with the [Strands Agents](https://strandsagents.com) framework (AWS's open-source agent SDK) over
41
+ AG-UI**: both on a custom backend (the [example backend](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend)) and on the official
42
+ [`ag-ui-strands`](https://pypi.org/project/ag-ui-strands/) adapter.
43
+
44
+ <div align="center">
45
+ <img src="https://raw.githubusercontent.com/rahrajlat/Gentui/main/docs/assets/demo.gif" alt="Gentui demo: ask, review the proposed command, approve, see the output, chart it" width="860">
46
+ </div>
47
+
48
+ ## Features
49
+
50
+ - **Works with any AG-UI backend.** Streaming text, tool calls and shared state work out of the box;
51
+ unknown tools show as a readable card, never an error.
52
+ - **Chain of thought, visible.** Reasoning streams into a collapsible "Thought for 3s" block.
53
+ - **Human-in-the-loop approval** built on AG-UI **interrupts**: the run ends waiting, your click
54
+ `resume`s it. The model can't approve its own commands.
55
+ - **Generative widgets from tool calls:** command card, command output, tables, terminal charts
56
+ (line, bar, scatter, histogram), live plan checklist.
57
+ - **Developer-friendly:** an event inspector (`d`) showing the raw SSE payloads exactly as sent, `/theme`,
58
+ `/clear`, `/reasoning`, and a clear [backend contract](https://github.com/rahrajlat/Gentui/blob/main/docs/tool-contract.md).
59
+ - **Yours to customise:** TOML config, hot-reloaded CSS, your own themes, and Python plugins that add
60
+ widgets, slash commands and event hooks.
61
+ - **Runs agents on AWS too:** invoke agents hosted on Amazon Bedrock AgentCore Runtime (AG-UI protocol) via boto3.
62
+ - **Backend-agnostic by design.** The client has no framework code; a complete example backend lives in
63
+ [`examples/strands-backend`](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend).
64
+
65
+ ## The sample agent: natural language → shell
66
+
67
+ The demo above is the bundled example backend, a **natural-language-to-shell agent** built on Strands
68
+ Agents. You describe a task in plain English, it proposes a single shell command, and **nothing runs
69
+ until you approve it**.
70
+
71
+ 1. **Ask:** "what are the 5 largest files here?"
72
+ 2. **Review:** a shell sub-agent writes one command for your shell (bash, or PowerShell on Windows)
73
+ with a one-line explanation and a risk level: `safe`, `caution` or `dangerous`.
74
+ 3. **Decide:** **Approve**, **Edit** the command first, or **Reject**. Your decision is sent back as an
75
+ AG-UI `resume`; the model can't approve for itself or change the command.
76
+ 4. **Run:** only the approved command executes, with a timeout, an output cap and a fixed working
77
+ directory. A denylist (recursive delete of root or home, disk formatting, shutdown, fork bombs,
78
+ interactive programs) is checked at proposal, at approval and again right before running. It is a
79
+ safety net, not a sandbox.
80
+
81
+ The same agent can also show results as a **table** or **chart**, lay out multi-step work as a live
82
+ **plan**, explain what a command does (an explainer sub-agent), and keep **long-term memory** between
83
+ conversations. It's a worked example of the [backend contract](https://github.com/rahrajlat/Gentui/blob/main/docs/tool-contract.md): copy it, or add your
84
+ own tools with [this guide](https://github.com/rahrajlat/Gentui/blob/main/examples/strands-backend/docs/add_a_tool.md).
85
+
86
+ ## Quick start
87
+
88
+ Requires [uv](https://docs.astral.sh/uv/) and Python 3.12.
89
+
90
+ ```bash
91
+ git clone https://github.com/rahrajlat/Gentui.git && cd Gentui
92
+ uv sync
93
+ uv run gentui http://localhost:8000/agent # your AG-UI endpoint
94
+ ```
95
+
96
+ No backend yet? Run the [sample natural-language-to-shell agent](#the-sample-agent-natural-language--shell)
97
+ (Strands Agents + FastAPI) in another terminal. It uses a local
98
+ [Ollama](https://ollama.com) by default; see its [README](https://github.com/rahrajlat/Gentui/blob/main/examples/strands-backend/README.md) for other providers:
99
+
100
+ ```bash
101
+ cd examples/strands-backend
102
+ uv sync && cp .env.example .env
103
+ uv run server # http://localhost:8000/agent
104
+ ```
105
+
106
+ ```bash
107
+ uv run gentui https://my.host/agent --token sk-... # bearer auth
108
+ uv run gentui URL -H "X-Org: acme" --theme nord --dev # extra header, theme, event inspector
109
+ ```
110
+
111
+ | Key / command | Does |
112
+ |---|---|
113
+ | `Enter` | send |
114
+ | `d` or `Ctrl+D` | toggle the event inspector |
115
+ | `Ctrl+Q` | quit |
116
+ | `/help` `/theme <name>` `/clear` `/reasoning` `/dev` `/quit` | slash commands |
117
+
118
+ ## Agents on Amazon Bedrock AgentCore Runtime
119
+
120
+ Gentui can also invoke an agent hosted on **[AgentCore Runtime](https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/what-is-bedrock-agentcore.html)**
121
+ with boto3's `invoke_agent_runtime`, using your normal AWS credentials. The runtime must be deployed with the
122
+ **AG-UI protocol**.
123
+
124
+ ```bash
125
+ uv sync --extra agentcore # boto3 is an optional extra
126
+ uv run gentui arn:aws:bedrock-agentcore:us-east-1:123456789012:runtime/my_agent-AbCdEfGhIj
127
+ uv run gentui ARN --profile dev --region eu-west-1 # optional: AWS profile and region
128
+ uv run gentui ARN --qualifier prod # optional: a specific runtime endpoint
129
+ ```
130
+
131
+ `--profile` and `--region` are both **optional**. Without them, Gentui uses the standard AWS credential chain
132
+ (`AWS_PROFILE`, SSO, environment variables) and the region in the ARN. They can also be set in `gentui.toml` as
133
+ `aws_profile` and `region`.
134
+
135
+ One conversation is one runtime session, errors come with fixes (missing credentials, denied access, wrong ARN), and
136
+ busy sessions are retried. Details, IAM permissions and troubleshooting: **[docs/agentcore.md](https://github.com/rahrajlat/Gentui/blob/main/docs/agentcore.md)**.
137
+ Both a runtime ARN and an endpoint ARN (`.../runtime-endpoint/DEFAULT`) work.
138
+
139
+ ## Configure
140
+
141
+ Put options in `./gentui.toml` or `~/.config/gentui/config.toml`. Flags, `GENTUI_URL` and
142
+ `GENTUI_TOKEN` override the file. Every option is documented in
143
+ [`gentui.example.toml`](https://github.com/rahrajlat/Gentui/blob/main/gentui.example.toml): backend URL, token and headers, props sent with every run,
144
+ title, welcome text, theme, splash and logo, reasoning on/off, timestamps, plugins and widget mapping.
145
+
146
+ > **Stateless backends** (ones that rebuild context from the message list, like the official
147
+ > `ag-ui-strands` adapter) need `send_history = true`. By default only the newest message is sent and
148
+ > the backend is expected to keep history per `threadId`.
149
+
150
+ ## Customise
151
+
152
+ - **Theme:** `theme = "nord"` or `/theme <name>`. The default is `gentui` (teal and violet); `claude`
153
+ (coral) is also built in.
154
+ - **Your own styling:** `css = "my.tcss"` loads a [Textual CSS](https://textual.textualize.io/guide/CSS/)
155
+ file on top of the defaults and **hot-reloads while the app runs**. Useful selectors: `.user`,
156
+ `.assistant`, `.thinking`, `.error`, `ToolWidget`, `#chat`, `#prompt`.
157
+ - **Your own widget for a backend tool:** subclass `ToolWidget`, then map it without any plugin file:
158
+
159
+ ```toml
160
+ [widgets]
161
+ show_map = "my_widgets:MapWidget"
162
+ ```
163
+
164
+ ## Plugins
165
+
166
+ A plugin is a plain Python file. Drop it in `./gentui_plugins/` or `~/.config/gentui/plugins/`, list it in
167
+ `plugins = [...]` or `--plugin`, or ship it as a pip package using the `gentui.plugins` entry point.
168
+
169
+ ```python
170
+ from gentui.plugins import on_event, register_command
171
+ from gentui.tui.widgets.base import ToolWidget
172
+ from gentui.tui.widgets.registry import register_widget
173
+
174
+ @register_widget("weather") # render tool calls named "weather"
175
+ class Weather(ToolWidget):
176
+ def on_end(self, args): self.show(f"☀ {args['city']}")
177
+
178
+ @register_command("ping", "say pong") # adds /ping
179
+ def ping(app, args): app.notify("pong")
180
+
181
+ @on_event("TOOL_CALL_RESULT") # hook any AG-UI event
182
+ async def audit(app, event): ...
183
+
184
+ def setup(app): ... # optional, runs once the app is mounted
185
+ ```
186
+
187
+ Plugins can mount any Textual widget into the conversation with `await app.mount_chat(widget)`. A
188
+ broken plugin is reported in a toast and never stops the app.
189
+
190
+ ## Build a backend for it
191
+
192
+ Any language works: serve a `POST` endpoint that streams AG-UI events. To get the rich widgets, name
193
+ your tools like this (anything else shows a JSON card). The full contract, including the approval
194
+ flow and a checklist, is in **[docs/tool-contract.md](https://github.com/rahrajlat/Gentui/blob/main/docs/tool-contract.md)**.
195
+
196
+ | Tool name | Arguments / result | Renders |
197
+ |---|---|---|
198
+ | `propose_command` | `{command, explanation, risk: safe\|caution\|dangerous}` | command card with Approve / Edit / Reject; the decision goes back as an AG-UI `resume` of the run's interrupt |
199
+ | `run_command` | result JSON `{command, exit_code, timed_out, truncated, output}` | output card |
200
+ | `show_table` | `{title, columns, rows}` | table |
201
+ | `show_chart` | `{type: line\|bar\|scatter\|histogram, title, x, series: [{name, values}], x_label, y_label, bins}` | terminal chart (plotext) |
202
+ | `search_memory` | `{query}` | quiet "◌ recalled …" line |
203
+ | `todo_write` + state `plan` | state `{"plan": [{content, status}]}` | live checklist |
204
+
205
+ ## How it works
206
+
207
+ ```
208
+ gentui (Textual) ── POST /agent (RunAgentInput) ──▶ any AG-UI backend
209
+ ▲ │
210
+ │◀────────────── SSE: AG-UI events ─────────────────┘
211
+
212
+ Approve ▸ `resume` of the run's interrupt ──▶ backend runs the approved command
213
+ ```
214
+
215
+ | Piece | File |
216
+ |---|---|
217
+ | SSE client (RunAgentInput in, typed events out) | [`tui/agui_client.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/agui_client.py) |
218
+ | Event → widget dispatch, interrupts, chat | [`tui/app.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/app.py) |
219
+ | Widgets and the tool-name registry | [`tui/widgets/`](https://github.com/rahrajlat/Gentui/tree/main/src/gentui/tui/widgets) |
220
+ | Logo, splash and animation | [`tui/branding.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/branding.py), [`tui/splash.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/tui/splash.py) |
221
+ | Plugin API and config | [`plugins.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/plugins.py), [`config.py`](https://github.com/rahrajlat/Gentui/blob/main/src/gentui/config.py) |
222
+
223
+ AG-UI events used: `RUN_STARTED/FINISHED/ERROR` (with `outcome: interrupt`), `TEXT_MESSAGE_*`,
224
+ `REASONING_*`, `TOOL_CALL_START/ARGS/END/RESULT`, `STATE_SNAPSHOT`, `STATE_DELTA`. The request side
225
+ uses `messages`, `forwardedProps` and `resume`.
226
+
227
+ ## Status
228
+
229
+ Gentui is **alpha**. What has been verified, and what has not:
230
+
231
+ - Built and tested against the **Strands Agents** framework (AWS) over AG-UI: the
232
+ [example backend](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend) and the official
233
+ [`ag-ui-strands`](https://pypi.org/project/ag-ui-strands/) adapter (with `send_history = true`).
234
+ - AgentCore Runtime support works against a real runtime (confirmed by the author with a plain runtime ARN) and only
235
+ covers runtimes using the AG-UI protocol. Other setups are covered by tests with a fake boto3 client and botocore's `Stubber`.
236
+ - Backends on other frameworks, the interrupt flow against a backend other than the example, other model
237
+ providers than Ollama, and native Windows are **untested**.
238
+ - The look relies on Unicode box-drawing and block characters. If glyphs are missing, try a terminal
239
+ font such as DejaVu Sans Mono, Cascadia or JetBrains Mono.
240
+
241
+ **Ideas, not built yet:** `show_form` / `ask_approval` tools, a composable JSON-tree UI tool, persistent
242
+ threads, a `--demo` mode and record/replay of runs.
243
+
244
+ ## Development
245
+
246
+ ```bash
247
+ uv run pytest -q # TUI tests: headless, no LLM or backend needed
248
+ cd examples/strands-backend && uv run pytest -q # the example backend's own tests
249
+ ```
250
+
251
+ The images above are generated from the app's own code:
252
+ `uv run --with pillow python docs/assets/build_assets.py`.
253
+
254
+ ## Contributing
255
+
256
+ Issues and pull requests are welcome. Please run both test suites before opening a PR, and add a test
257
+ with any behaviour change. Because Gentui is a client for an open protocol, changes that keep it
258
+ backend-agnostic are the easiest to accept.
259
+
260
+ ## License
261
+
262
+ [MIT](https://github.com/rahrajlat/Gentui/blob/main/LICENSE). Free to use, modify and distribute, including the [example backend](https://github.com/rahrajlat/Gentui/tree/main/examples/strands-backend).
@@ -0,0 +1,69 @@
1
+ [project]
2
+ name = "gentui"
3
+ version = "0.1.0"
4
+ description = "A terminal interface for prototyping agents really quickly, for any AG-UI backend"
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ keywords = [
9
+ "ag-ui",
10
+ "agents",
11
+ "ai-agents",
12
+ "tui",
13
+ "terminal",
14
+ "textual",
15
+ "llm",
16
+ "human-in-the-loop",
17
+ "strands",
18
+ "agentcore",
19
+ ]
20
+ classifiers = [
21
+ "Development Status :: 3 - Alpha",
22
+ "Environment :: Console",
23
+ "Intended Audience :: Developers",
24
+ "Operating System :: OS Independent",
25
+ "Programming Language :: Python :: 3",
26
+ "Programming Language :: Python :: 3.12",
27
+ "Topic :: Software Development",
28
+ "Topic :: Terminals",
29
+ ]
30
+ requires-python = ">=3.12"
31
+ dependencies = [
32
+ "ag-ui-protocol>=1.0.0",
33
+ "httpx>=0.28.1",
34
+ "jsonpatch>=1.33",
35
+ "textual>=8.2.8",
36
+ "textual-plotext>=1.0.1",
37
+ ]
38
+
39
+ [[project.authors]]
40
+ name = "rahrajlat"
41
+
42
+ [project.urls]
43
+ Homepage = "https://github.com/rahrajlat/Gentui"
44
+ Repository = "https://github.com/rahrajlat/Gentui"
45
+ Documentation = "https://github.com/rahrajlat/Gentui#readme"
46
+ Issues = "https://github.com/rahrajlat/Gentui/issues"
47
+ Changelog = "https://github.com/rahrajlat/Gentui/blob/main/CHANGELOG.md"
48
+
49
+ [project.scripts]
50
+ gentui = "gentui.cli:main"
51
+ tui = "gentui.cli:main"
52
+
53
+ [project.optional-dependencies]
54
+ agentcore = ["boto3>=1.40"]
55
+
56
+ [build-system]
57
+ requires = ["uv_build>=0.12.22,<0.13.0"]
58
+ build-backend = "uv_build"
59
+
60
+ [dependency-groups]
61
+ dev = [
62
+ "boto3>=1.43.108",
63
+ "pytest>=9.1.1",
64
+ "pytest-asyncio>=1.4.0",
65
+ ]
66
+
67
+ [tool.pytest.ini_options]
68
+ asyncio_mode = "auto"
69
+ testpaths = ["tests"]