batrachian-toad 0.5.0a8__tar.gz → 0.5.8__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.
- batrachian_toad-0.5.8/CHANGELOG.md +50 -0
- batrachian_toad-0.5.8/CONTRIBUTING.md +8 -0
- batrachian_toad-0.5.8/PKG-INFO +167 -0
- batrachian_toad-0.5.8/README.md +144 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/pyproject.toml +3 -3
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/acp/agent.py +32 -6
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/acp/messages.py +6 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/agent.py +3 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/ansi/_ansi.py +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/ansi/_stream_parser.py +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/app.py +47 -19
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/cli.py +40 -24
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/danger.py +2 -2
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/claude.com.toml +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/inference.huggingface.co.toml +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/openhands.dev.toml +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/directory.py +16 -35
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/fuzzy.py +1 -4
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/jsonrpc.py +1 -1
- batrachian_toad-0.5.8/src/toad/path_filter.py +119 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/paths.py +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/prompt/extract.py +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/agent_modal.py +20 -2
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/main.py +3 -3
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/settings.py +3 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/store.py +54 -18
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/store.tcss +25 -2
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/settings_schema.py +35 -21
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/toad.tcss +61 -19
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/condensed_path.py +17 -6
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/conversation.py +36 -7
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/flash.py +1 -2
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/grid_select.py +26 -11
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/highlighted_textarea.py +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/path_search.py +34 -36
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/prompt.py +33 -7
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/question.py +11 -3
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/tool_call.py +1 -1
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/uv.lock +26 -112
- batrachian_toad-0.5.0a8/PKG-INFO +0 -123
- batrachian_toad-0.5.0a8/README.md +0 -100
- batrachian_toad-0.5.0a8/ansi_mandel.py +0 -87
- batrachian_toad-0.5.0a8/ansi_test.py +0 -15
- batrachian_toad-0.5.0a8/box_test.py +0 -4
- batrachian_toad-0.5.0a8/cpr.py +0 -39
- batrachian_toad-0.5.0a8/cursor_test.py +0 -8
- batrachian_toad-0.5.0a8/difffail.jsonl +0 -9
- batrachian_toad-0.5.0a8/mandel.py +0 -32
- batrachian_toad-0.5.0a8/mandelbrot.py +0 -51
- batrachian_toad-0.5.0a8/scroll_test.py +0 -6
- batrachian_toad-0.5.0a8/simple_test.py +0 -5
- batrachian_toad-0.5.0a8/table_movie.py +0 -197
- batrachian_toad-0.5.0a8/terminal_test.py +0 -297
- batrachian_toad-0.5.0a8/test_cursor_toggle.py +0 -7
- batrachian_toad-0.5.0a8/test_flow.py +0 -1
- batrachian_toad-0.5.0a8/test_ind.py +0 -48
- batrachian_toad-0.5.0a8/test_input.py +0 -2
- batrachian_toad-0.5.0a8/test_pygments.py +0 -18
- batrachian_toad-0.5.0a8/test_scroll.py +0 -5
- batrachian_toad-0.5.0a8/test_scroll1.py +0 -309
- batrachian_toad-0.5.0a8/test_scroll2.py +0 -82
- batrachian_toad-0.5.0a8/test_scroll_margins.py +0 -45
- batrachian_toad-0.5.0a8/test_scroll_region.py +0 -10
- batrachian_toad-0.5.0a8/test_size.py +0 -5
- batrachian_toad-0.5.0a8/tool.jsonl +0 -26
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/.gitignore +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/.python-version +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/LICENSE +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/Makefile +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/notes.md +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/project/calculator.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/project/calculator.tcss +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/__init__.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/__main__.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/_loop.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/about.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/acp/api.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/acp/encode_tool_call_id.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/acp/prompt.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/acp/protocol.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/agent_schema.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/agents.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/ansi/__init__.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/ansi/_ansi_colors.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/ansi/_control_codes.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/ansi/_keys.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/ansi/_sgr_styles.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/answer.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/atomic.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/code_analyze.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/complete.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/constants.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/conversation_markdown.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/ampcode.com.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/augmentcode.com.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/docker.com.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/geminicli.com.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/goose.ai.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/kimi.com.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/openai.com.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/opencode.ai.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/stakpak.dev.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/vibe.mistral.ai.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/data/agents/vtcode.dev.toml +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/db.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/dec.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/gist.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/history.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/menus.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/messages.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/option_content.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/os.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/path_complete.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/pill.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/prompt/resource.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/protocol.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/action_modal.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/permissions.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/permissions.tcss +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/screens/settings.tcss +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/settings.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/shell.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/shell_read.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/slash_command.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/version.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/visuals/columns.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/agent_response.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/agent_thought.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/command_pane.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/danger_warning.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/diff_view.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/future_text.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/mandelbrot.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/markdown_note.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/menu.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/non_selectable_label.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/note.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/plan.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/project_directory_tree.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/shell_result.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/shell_terminal.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/side_bar.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/slash_complete.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/strike_text.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/terminal.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/terminal_tool.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/throbber.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/user_input.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/version.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/src/toad/widgets/welcome.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8/tools}/echo_client.py +0 -0
- {batrachian_toad-0.5.0a8 → batrachian_toad-0.5.8}/tools/make_qr.py +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.5.8] - 2025-12-26
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fixed broken tool calls
|
|
13
|
+
|
|
14
|
+
## [0.5.7] - 2025-12-26
|
|
15
|
+
|
|
16
|
+
### Changes
|
|
17
|
+
|
|
18
|
+
- Cursor keys can navigate between sections in the store screen
|
|
19
|
+
- Optimized path search
|
|
20
|
+
- Disabled path search in shell mode
|
|
21
|
+
- Typing in the conversation view will auto-focus the prompt
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Added single character switches https://github.com/batrachianai/toad/pull/135
|
|
26
|
+
|
|
27
|
+
## [0.5.6] - 2025-12-24
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Fixed agent selector not focusing on run.
|
|
32
|
+
- Added project directory as second argument to `toad acp` rather than a switch.
|
|
33
|
+
|
|
34
|
+
## [0.5.5] - 2025-12-22
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- Fixed column setting not taking effect
|
|
39
|
+
|
|
40
|
+
## [0.5.0] - 2025-12-18
|
|
41
|
+
|
|
42
|
+
### Added
|
|
43
|
+
|
|
44
|
+
- First release. This document will be updated for subsequent releases.
|
|
45
|
+
|
|
46
|
+
[0.5.8]: https://github.com/Textualize/textual/compare/v0.5.7...v0.5.8
|
|
47
|
+
[0.5.7]: https://github.com/Textualize/textual/compare/v0.5.6...v0.5.7
|
|
48
|
+
[0.5.6]: https://github.com/Textualize/textual/compare/v0.5.5...v0.5.6
|
|
49
|
+
[0.5.5]: https://github.com/Textualize/textual/compare/v0.5.0...v0.5.5
|
|
50
|
+
[0.5.0]: https://github.com/batrachianai/toad/releases/tag/v0.5.0
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Guide to Contributing
|
|
2
|
+
|
|
3
|
+
Thank you for your interesting in improving Toad!
|
|
4
|
+
|
|
5
|
+
If you are thinking of fixing a bug or contributing a feature, please open a Discussion first.
|
|
6
|
+
You will be asked for a link to the discussion when you contribute a PR.
|
|
7
|
+
|
|
8
|
+
TODO: add technical help
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: batrachian-toad
|
|
3
|
+
Version: 0.5.8
|
|
4
|
+
Summary: A unified experience for AI in your terminal.
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.14
|
|
7
|
+
Requires-Dist: bashlex>=0.18
|
|
8
|
+
Requires-Dist: click>=8.2.1
|
|
9
|
+
Requires-Dist: gitpython>=3.1.44
|
|
10
|
+
Requires-Dist: google-re2>=1.1.20251105
|
|
11
|
+
Requires-Dist: httpx>=0.28.1
|
|
12
|
+
Requires-Dist: packaging>=25.0
|
|
13
|
+
Requires-Dist: pathspec>=0.12.1
|
|
14
|
+
Requires-Dist: platformdirs>=4.3.8
|
|
15
|
+
Requires-Dist: rich
|
|
16
|
+
Requires-Dist: textual-serve>=1.1.2
|
|
17
|
+
Requires-Dist: textual-speedups==0.2.1
|
|
18
|
+
Requires-Dist: textual[syntax]>=6.11.0
|
|
19
|
+
Requires-Dist: tree-sitter>=0.24.0
|
|
20
|
+
Requires-Dist: typeguard>=4.4.4
|
|
21
|
+
Requires-Dist: xdg-base-dirs>=6.0.2
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# Toad
|
|
25
|
+
|
|
26
|
+
A unified interface for AI in your terminal ([release announcement](https://willmcgugan.github.io/toad-released/)).
|
|
27
|
+
|
|
28
|
+
Run coding agents seamlessly under a single beautiful terminal UI, thanks to the [ACP](https://agentclientprotocol.com/protocol/initialization) protocol.
|
|
29
|
+
|
|
30
|
+
<table>
|
|
31
|
+
|
|
32
|
+
<tbody>
|
|
33
|
+
|
|
34
|
+
<tr>
|
|
35
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 58 58" src="https://github.com/user-attachments/assets/98387559-2e10-485a-8a7d-82cb00ed7622" /></td>
|
|
36
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 59 04" src="https://github.com/user-attachments/assets/d4231320-b678-47ba-99ce-02746ca2622b" /></td>
|
|
37
|
+
</tr>
|
|
38
|
+
|
|
39
|
+
<tr>
|
|
40
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 59 22" src="https://github.com/user-attachments/assets/ddba550d-ff33-45ad-9f93-281187f5c974" /></td>
|
|
41
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 59 37" src="https://github.com/user-attachments/assets/e7943272-39a5-40a1-bedf-e440002e1290" /></td>
|
|
42
|
+
</tr>
|
|
43
|
+
|
|
44
|
+
</tbody>
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
</table>
|
|
48
|
+
|
|
49
|
+
## Compatibility
|
|
50
|
+
|
|
51
|
+
Toad runs on Linux and macOS. Native Windows support is currently lacking (but on the roadmap), but Toad will run quite well with WSL.
|
|
52
|
+
|
|
53
|
+
Toad is a terminal application.
|
|
54
|
+
Any terminal will work, although if you are using the default terminal on macOS you will get a much reduced experience.
|
|
55
|
+
I recommend [Ghostty](https://ghostty.org/) which is fully featured and has amazing performance.
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
## Getting Started
|
|
59
|
+
|
|
60
|
+
The easiest way to install Toad is by pasting the following in to your terminal:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
curl -fsSL batrachian.ai/install | sh
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
You should now have `toad` installed.
|
|
67
|
+
|
|
68
|
+
If that doesn't work for any reason, then you can install with the following steps:
|
|
69
|
+
|
|
70
|
+
First [install UV](https://docs.astral.sh/uv/getting-started/installation/):
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Then use UV to install toad:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
uv tool install -U batrachian-toad --python 3.14
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Using Toad
|
|
83
|
+
|
|
84
|
+
Launch Toad with the following:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
toad
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
You should see something like this:
|
|
91
|
+
|
|
92
|
+
<img width="1266" height="994" alt="front-fs8" src="https://github.com/user-attachments/assets/8831f7de-5349-4b3f-9de9-d4565b513108" />
|
|
93
|
+
|
|
94
|
+
From this screen you will be able to find, install, and launch a coding agent.
|
|
95
|
+
If you already have an agent installed, you can skip the install step.
|
|
96
|
+
To launch an agent, select it and press space.
|
|
97
|
+
|
|
98
|
+
The footer will always display the most significant keys for the current context.
|
|
99
|
+
To see all the keys, summon the command palette with `ctrl+p` and search for "keys".
|
|
100
|
+
|
|
101
|
+
### Toad CLI
|
|
102
|
+
|
|
103
|
+
When running Toad, the current working directory is assumed to be your project directory.
|
|
104
|
+
To use another project directory, add the path to the command.
|
|
105
|
+
For example:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
toad ~/projects/my-awesome-app
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
If you want to skip the initial agent screen, add the `-a` switch with the name of your chosen agent.
|
|
112
|
+
For example:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
toad -a open-hands
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
To see all subcommands and switches, add the `--help` switch:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
toad --help
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Web server
|
|
125
|
+
|
|
126
|
+
You can run Toad as a web application.
|
|
127
|
+
|
|
128
|
+
Run the following, and click the link in the terminal:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
toad serve
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+

|
|
135
|
+
|
|
136
|
+
## Toad development
|
|
137
|
+
|
|
138
|
+
Toad was built by [Will McGugan](https://github.com/willmcgugan) and is currently under active development.
|
|
139
|
+
|
|
140
|
+
To discuss Toad, see the Discussions tab, or join the #toad channel on the [Textualize discord server](https://discord.gg/Enf6Z3qhVr).
|
|
141
|
+
|
|
142
|
+
### Roadmap
|
|
143
|
+
|
|
144
|
+
Some planned features:
|
|
145
|
+
|
|
146
|
+
- UI for MCP servers
|
|
147
|
+
- Expose model selection (waiting on ACP update)
|
|
148
|
+
- Sessions
|
|
149
|
+
- Multiple agents
|
|
150
|
+
- Windows native support
|
|
151
|
+
|
|
152
|
+
### Reporting bugs
|
|
153
|
+
|
|
154
|
+
This project is trialling a non-traditional approach to issues.
|
|
155
|
+
Before an issue is created, there must be a post in Dicussions, approved by a Toad dev (Currently @willmcgugan).
|
|
156
|
+
|
|
157
|
+
By allowing the discussions to happen in the Discussion tabs, issues can be reserved for actionable tasks with a clear description and goal.
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# Toad
|
|
2
|
+
|
|
3
|
+
A unified interface for AI in your terminal ([release announcement](https://willmcgugan.github.io/toad-released/)).
|
|
4
|
+
|
|
5
|
+
Run coding agents seamlessly under a single beautiful terminal UI, thanks to the [ACP](https://agentclientprotocol.com/protocol/initialization) protocol.
|
|
6
|
+
|
|
7
|
+
<table>
|
|
8
|
+
|
|
9
|
+
<tbody>
|
|
10
|
+
|
|
11
|
+
<tr>
|
|
12
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 58 58" src="https://github.com/user-attachments/assets/98387559-2e10-485a-8a7d-82cb00ed7622" /></td>
|
|
13
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 59 04" src="https://github.com/user-attachments/assets/d4231320-b678-47ba-99ce-02746ca2622b" /></td>
|
|
14
|
+
</tr>
|
|
15
|
+
|
|
16
|
+
<tr>
|
|
17
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 59 22" src="https://github.com/user-attachments/assets/ddba550d-ff33-45ad-9f93-281187f5c974" /></td>
|
|
18
|
+
<td><img width="1338" height="1004" alt="Screenshot 2025-10-23 at 08 59 37" src="https://github.com/user-attachments/assets/e7943272-39a5-40a1-bedf-e440002e1290" /></td>
|
|
19
|
+
</tr>
|
|
20
|
+
|
|
21
|
+
</tbody>
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
</table>
|
|
25
|
+
|
|
26
|
+
## Compatibility
|
|
27
|
+
|
|
28
|
+
Toad runs on Linux and macOS. Native Windows support is currently lacking (but on the roadmap), but Toad will run quite well with WSL.
|
|
29
|
+
|
|
30
|
+
Toad is a terminal application.
|
|
31
|
+
Any terminal will work, although if you are using the default terminal on macOS you will get a much reduced experience.
|
|
32
|
+
I recommend [Ghostty](https://ghostty.org/) which is fully featured and has amazing performance.
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## Getting Started
|
|
36
|
+
|
|
37
|
+
The easiest way to install Toad is by pasting the following in to your terminal:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
curl -fsSL batrachian.ai/install | sh
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
You should now have `toad` installed.
|
|
44
|
+
|
|
45
|
+
If that doesn't work for any reason, then you can install with the following steps:
|
|
46
|
+
|
|
47
|
+
First [install UV](https://docs.astral.sh/uv/getting-started/installation/):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
curl -LsSf https://astral.sh/uv/install.sh | sh
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then use UV to install toad:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uv tool install -U batrachian-toad --python 3.14
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Using Toad
|
|
60
|
+
|
|
61
|
+
Launch Toad with the following:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
toad
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
You should see something like this:
|
|
68
|
+
|
|
69
|
+
<img width="1266" height="994" alt="front-fs8" src="https://github.com/user-attachments/assets/8831f7de-5349-4b3f-9de9-d4565b513108" />
|
|
70
|
+
|
|
71
|
+
From this screen you will be able to find, install, and launch a coding agent.
|
|
72
|
+
If you already have an agent installed, you can skip the install step.
|
|
73
|
+
To launch an agent, select it and press space.
|
|
74
|
+
|
|
75
|
+
The footer will always display the most significant keys for the current context.
|
|
76
|
+
To see all the keys, summon the command palette with `ctrl+p` and search for "keys".
|
|
77
|
+
|
|
78
|
+
### Toad CLI
|
|
79
|
+
|
|
80
|
+
When running Toad, the current working directory is assumed to be your project directory.
|
|
81
|
+
To use another project directory, add the path to the command.
|
|
82
|
+
For example:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
toad ~/projects/my-awesome-app
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
If you want to skip the initial agent screen, add the `-a` switch with the name of your chosen agent.
|
|
89
|
+
For example:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
toad -a open-hands
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
To see all subcommands and switches, add the `--help` switch:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
toad --help
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Web server
|
|
102
|
+
|
|
103
|
+
You can run Toad as a web application.
|
|
104
|
+
|
|
105
|
+
Run the following, and click the link in the terminal:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
toad serve
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+

|
|
112
|
+
|
|
113
|
+
## Toad development
|
|
114
|
+
|
|
115
|
+
Toad was built by [Will McGugan](https://github.com/willmcgugan) and is currently under active development.
|
|
116
|
+
|
|
117
|
+
To discuss Toad, see the Discussions tab, or join the #toad channel on the [Textualize discord server](https://discord.gg/Enf6Z3qhVr).
|
|
118
|
+
|
|
119
|
+
### Roadmap
|
|
120
|
+
|
|
121
|
+
Some planned features:
|
|
122
|
+
|
|
123
|
+
- UI for MCP servers
|
|
124
|
+
- Expose model selection (waiting on ACP update)
|
|
125
|
+
- Sessions
|
|
126
|
+
- Multiple agents
|
|
127
|
+
- Windows native support
|
|
128
|
+
|
|
129
|
+
### Reporting bugs
|
|
130
|
+
|
|
131
|
+
This project is trialling a non-traditional approach to issues.
|
|
132
|
+
Before an issue is created, there must be a post in Dicussions, approved by a Toad dev (Currently @willmcgugan).
|
|
133
|
+
|
|
134
|
+
By allowing the discussions to happen in the Discussion tabs, issues can be reserved for actionable tasks with a clear description and goal.
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "batrachian-toad"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.8"
|
|
4
4
|
description = "A unified experience for AI in your terminal."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.14"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"textual[syntax]>=6.
|
|
8
|
+
"textual[syntax]>=6.11.0",
|
|
9
9
|
"click>=8.2.1",
|
|
10
10
|
"gitpython>=3.1.44",
|
|
11
11
|
"tree-sitter>=0.24.0",
|
|
@@ -17,9 +17,9 @@ dependencies = [
|
|
|
17
17
|
"textual-serve>=1.1.2",
|
|
18
18
|
"textual-speedups==0.2.1",
|
|
19
19
|
"packaging>=25.0",
|
|
20
|
-
"posthog>=7.0.1",
|
|
21
20
|
"bashlex>=0.18",
|
|
22
21
|
"pathspec>=0.12.1",
|
|
22
|
+
"google-re2>=1.1.20251105",
|
|
23
23
|
]
|
|
24
24
|
|
|
25
25
|
[tool.uv.workspace]
|
|
@@ -3,7 +3,7 @@ import asyncio
|
|
|
3
3
|
import json
|
|
4
4
|
import os
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import cast, NamedTuple
|
|
6
|
+
from typing import Any, cast, NamedTuple
|
|
7
7
|
from copy import deepcopy
|
|
8
8
|
|
|
9
9
|
import rich.repr
|
|
@@ -125,11 +125,22 @@ class Agent(AgentBase):
|
|
|
125
125
|
return message_target.post_message(message)
|
|
126
126
|
|
|
127
127
|
@jsonrpc.expose("session/update")
|
|
128
|
-
def rpc_session_update(
|
|
128
|
+
def rpc_session_update(
|
|
129
|
+
self,
|
|
130
|
+
sessionId: str,
|
|
131
|
+
update: protocol.SessionUpdate,
|
|
132
|
+
_meta: dict[str, Any] | None = None,
|
|
133
|
+
):
|
|
129
134
|
"""Agent requests an update.
|
|
130
135
|
|
|
131
136
|
https://agentclientprotocol.com/protocol/schema
|
|
132
137
|
"""
|
|
138
|
+
status_line: str | None = None
|
|
139
|
+
if _meta and (field_meta := _meta.get("field_meta")) is not None:
|
|
140
|
+
if (
|
|
141
|
+
open_hands_metrics := field_meta.get("openhands.dev/metrics")
|
|
142
|
+
) is not None:
|
|
143
|
+
status_line = open_hands_metrics.get("status_line")
|
|
133
144
|
|
|
134
145
|
match update:
|
|
135
146
|
case {
|
|
@@ -190,6 +201,9 @@ class Agent(AgentBase):
|
|
|
190
201
|
case {"sessionUpdate": "current_mode_update", "currentModeId": mode_id}:
|
|
191
202
|
self.post_message(messages.ModeUpdate(mode_id))
|
|
192
203
|
|
|
204
|
+
if status_line is not None:
|
|
205
|
+
self.post_message(messages.UpdateStatusLine(status_line))
|
|
206
|
+
|
|
193
207
|
@jsonrpc.expose("session/request_permission")
|
|
194
208
|
async def rpc_request_permission(
|
|
195
209
|
self,
|
|
@@ -359,7 +373,10 @@ class Agent(AgentBase):
|
|
|
359
373
|
async def _run_agent(self) -> None:
|
|
360
374
|
"""Task to communicate with the agent subprocess."""
|
|
361
375
|
|
|
362
|
-
|
|
376
|
+
if constants.DEBUG:
|
|
377
|
+
agent_output = open("agent.jsonl", "wb")
|
|
378
|
+
else:
|
|
379
|
+
agent_output = None
|
|
363
380
|
|
|
364
381
|
PIPE = asyncio.subprocess.PIPE
|
|
365
382
|
env = os.environ.copy()
|
|
@@ -411,8 +428,9 @@ class Agent(AgentBase):
|
|
|
411
428
|
if not line.strip():
|
|
412
429
|
continue
|
|
413
430
|
|
|
414
|
-
agent_output
|
|
415
|
-
|
|
431
|
+
if agent_output is not None:
|
|
432
|
+
agent_output.write(line)
|
|
433
|
+
agent_output.flush()
|
|
416
434
|
|
|
417
435
|
try:
|
|
418
436
|
line_str = line.decode("utf-8")
|
|
@@ -464,7 +482,15 @@ class Agent(AgentBase):
|
|
|
464
482
|
)
|
|
465
483
|
)
|
|
466
484
|
|
|
467
|
-
agent_output
|
|
485
|
+
if agent_output is not None:
|
|
486
|
+
agent_output.close()
|
|
487
|
+
|
|
488
|
+
self._process = None
|
|
489
|
+
|
|
490
|
+
async def stop(self) -> None:
|
|
491
|
+
"""Gracefully stop the process."""
|
|
492
|
+
if self._process is not None:
|
|
493
|
+
self._process.terminate()
|
|
468
494
|
|
|
469
495
|
async def run(self) -> None:
|
|
470
496
|
"""The main logic of the Agent."""
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
|
|
5
5
|
from asyncio import Future
|
|
6
|
-
from typing import Mapping, TYPE_CHECKING
|
|
6
|
+
from typing import Any, Mapping, TYPE_CHECKING
|
|
7
7
|
from textual.message import Message
|
|
8
8
|
|
|
9
9
|
import rich.repr
|
|
@@ -27,6 +27,11 @@ class Thinking(AgentMessage):
|
|
|
27
27
|
text: str
|
|
28
28
|
|
|
29
29
|
|
|
30
|
+
@dataclass
|
|
31
|
+
class UpdateStatusLine(AgentMessage):
|
|
32
|
+
status_line: str
|
|
33
|
+
|
|
34
|
+
|
|
30
35
|
@dataclass
|
|
31
36
|
class Update(AgentMessage):
|
|
32
37
|
type: str
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
from datetime import datetime, timezone
|
|
2
3
|
from functools import cached_property
|
|
3
4
|
from pathlib import Path
|
|
4
5
|
import json
|
|
@@ -7,15 +8,14 @@ from typing import Any, ClassVar, TYPE_CHECKING
|
|
|
7
8
|
|
|
8
9
|
from rich import terminal_theme
|
|
9
10
|
|
|
10
|
-
from textual import work
|
|
11
|
+
from textual import on, work
|
|
11
12
|
from textual.binding import Binding, BindingType
|
|
12
13
|
from textual.reactive import var, reactive
|
|
13
14
|
from textual.app import App
|
|
15
|
+
from textual import events
|
|
14
16
|
from textual.signal import Signal
|
|
15
17
|
|
|
16
18
|
|
|
17
|
-
from posthog import Posthog
|
|
18
|
-
|
|
19
19
|
from toad.settings import Schema, Settings
|
|
20
20
|
from toad.agent_schema import Agent as AgentData
|
|
21
21
|
from toad.settings_schema import SCHEMA
|
|
@@ -29,12 +29,6 @@ if TYPE_CHECKING:
|
|
|
29
29
|
from toad.screens.store import StoreScreen
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
import warnings
|
|
33
|
-
|
|
34
|
-
# TODO: Look in to Posthog Syntax warnings
|
|
35
|
-
warnings.filterwarnings("ignore", category=SyntaxWarning)
|
|
36
|
-
|
|
37
|
-
|
|
38
32
|
DRACULA_TERMINAL_THEME = terminal_theme.TerminalTheme(
|
|
39
33
|
background=(40, 42, 54), # #282A36
|
|
40
34
|
foreground=(248, 248, 242), # #F8F8F2
|
|
@@ -217,6 +211,8 @@ def get_store_screen() -> StoreScreen:
|
|
|
217
211
|
|
|
218
212
|
|
|
219
213
|
class ToadApp(App, inherit_bindings=False):
|
|
214
|
+
"""The top level app."""
|
|
215
|
+
|
|
220
216
|
SCREENS = {"settings": get_settings_screen}
|
|
221
217
|
MODES = {"store": get_store_screen}
|
|
222
218
|
BINDING_GROUP_TITLE = "System"
|
|
@@ -268,10 +264,7 @@ class ToadApp(App, inherit_bindings=False):
|
|
|
268
264
|
)
|
|
269
265
|
self._initial_mode = mode
|
|
270
266
|
self.version_meta: VersionMeta | None = None
|
|
271
|
-
|
|
272
|
-
project_api_key="phc_mJWPV7GP3ar1i9vxBg2U8aiKsjNgVwum6F6ZggaD4ri",
|
|
273
|
-
host="https://us.i.posthog.com",
|
|
274
|
-
)
|
|
267
|
+
|
|
275
268
|
super().__init__()
|
|
276
269
|
|
|
277
270
|
@property
|
|
@@ -324,13 +317,30 @@ class ToadApp(App, inherit_bindings=False):
|
|
|
324
317
|
if not self.settings.get("statistics.allow_collect", bool):
|
|
325
318
|
# User has disabled stats
|
|
326
319
|
return
|
|
320
|
+
|
|
321
|
+
POSTHOG_API_KEY = "phc_mJWPV7GP3ar1i9vxBg2U8aiKsjNgVwum6F6ZggaD4ri"
|
|
322
|
+
POSTHOG_HOST = "https://us.i.posthog.com"
|
|
323
|
+
POSTHOG_EVENT_URL = f"{POSTHOG_HOST}/i/v0/e/"
|
|
324
|
+
|
|
325
|
+
import platform
|
|
326
|
+
import httpx
|
|
327
|
+
|
|
328
|
+
timestamp = datetime.now(timezone.utc).isoformat()
|
|
329
|
+
|
|
327
330
|
event_properties = {"toad_version": self.version} | properties
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
event_name,
|
|
331
|
-
distinct_id
|
|
332
|
-
properties
|
|
333
|
-
|
|
331
|
+
body_json = {
|
|
332
|
+
"api_key": POSTHOG_API_KEY,
|
|
333
|
+
"event": event_name,
|
|
334
|
+
"distinct_id": self.anon_id,
|
|
335
|
+
"properties": event_properties,
|
|
336
|
+
"timestamp": timestamp,
|
|
337
|
+
"os": platform.system(),
|
|
338
|
+
}
|
|
339
|
+
try:
|
|
340
|
+
async with httpx.AsyncClient() as client:
|
|
341
|
+
await client.post(POSTHOG_EVENT_URL, json=body_json)
|
|
342
|
+
except Exception:
|
|
343
|
+
pass
|
|
334
344
|
|
|
335
345
|
def save_settings(self) -> None:
|
|
336
346
|
if self.settings.changed:
|
|
@@ -355,8 +365,16 @@ class ToadApp(App, inherit_bindings=False):
|
|
|
355
365
|
elif key == "ui.scrollbar":
|
|
356
366
|
if isinstance(value, str):
|
|
357
367
|
self.scrollbar = value
|
|
368
|
+
elif key == "ui.compact-input":
|
|
369
|
+
self.set_class(bool(value), "-compact-input")
|
|
358
370
|
elif key == "ui.footer":
|
|
359
371
|
self.set_class(not bool(value), "-hide-footer")
|
|
372
|
+
elif key == "ui.status-line":
|
|
373
|
+
self.set_class(not bool(value), "-hide-status-line")
|
|
374
|
+
elif key == "ui.agent-title":
|
|
375
|
+
self.set_class(not bool(value), "-hide-agent-title")
|
|
376
|
+
elif key == "ui.info-bar":
|
|
377
|
+
self.set_class(not bool(value), "-hide-info-bar")
|
|
360
378
|
elif key == "agent.thoughts":
|
|
361
379
|
self.set_class(not bool(value), "-hide-thoughts")
|
|
362
380
|
elif key == "sidebar.hide":
|
|
@@ -387,6 +405,16 @@ class ToadApp(App, inherit_bindings=False):
|
|
|
387
405
|
|
|
388
406
|
self.set_timer(1, self.run_version_check)
|
|
389
407
|
|
|
408
|
+
@on(events.TextSelected)
|
|
409
|
+
async def on_text_selected(self) -> None:
|
|
410
|
+
if self.settings.get("ui.auto_copy", bool):
|
|
411
|
+
if (selection := self.screen.get_selected_text()) is not None:
|
|
412
|
+
self.copy_to_clipboard(selection)
|
|
413
|
+
self.notify(
|
|
414
|
+
"Copied selection to clipboard (see settings)",
|
|
415
|
+
title="Automatic copy",
|
|
416
|
+
)
|
|
417
|
+
|
|
390
418
|
def run_on_exit(self):
|
|
391
419
|
if self.update_required and self.version_meta is not None:
|
|
392
420
|
version_meta = self.version_meta
|