Context
This repository was extracted from the BrokkAi/brokk monorepo via git filter-repo --subdirectory-filter brokk-code to host the launcher / CLI surface of the former "brokk-code" Python project. The interactive Textual TUI is deprecated; brokk-cli continues to ship as the launcher for:
brokk acp — headless ACP server over stdio (native Java ACP via mcp_launcher.run_acp_server)
brokk bifrost --workspace . — Rust MCP server bootstrap
brokk login / brokk logout / brokk github login|logout|status
brokk install <editor> — Neovim / Zed / IntelliJ / Codex integration installers
brokk issue create|diagnose|solve, brokk pr create|review, brokk commit, brokk exec
brokk mcp, brokk mcp-core, brokk version
- Java executor JAR download/lifecycle and bifrost binary management
This issue removes every TUI-only file/dependency in a single PR. Total reduction: ~7500 LOC + the textual runtime dependency.
Bumps the version to 0.9.0 (breaking: TUI surface removed) and tags v0.9.0 to trigger the first PyPI publish from this repo.
Acceptance criteria
Step 1 — Branch
git checkout master && git pull --ff-only
git checkout -b feat/remove-tui
Step 2 — Delete TUI source files and directories
git rm brokk_code/app.py # 184K, ~4600 LOC, sole Textual App
git rm brokk_code/settings_modal.py # 40K, Textual ModalScreen
git rm brokk_code/prompt_history.py # 4K, history persistence consumed only by BrokkApp
git rm brokk_code/session_persistence.py # 8K, session zip/resume, BrokkApp-only
git rm brokk_code/welcome.py # 4K, TUI splash text + braille icon
git rm -r brokk_code/widgets/ # 15 files, 436K — chat panel, token bar, status line, task list, etc.
git rm -r brokk_code/modals/ # 4 files, 28K — Textual ModalScreen subclasses
git rm -r brokk_code/styles/ # 2 .tcss files, 24K — Textual stylesheet
Confirm with grep -rln '^from textual\\|^import textual' brokk_code/ that no import of textual remains in brokk_code/. Today every match is inside the files above.
Step 3 — Delete TUI-only tests (29 files)
git rm tests/test_app_cost.py \\
tests/test_autocommit_toggle.py \\
tests/test_brokkapp_shutdown.py \\
tests/test_chat_panel.py \\
tests/test_chat_panel_layout.py \\
tests/test_footer_removed.py \\
tests/test_mode_toggle.py \\
tests/test_model_command_menu.py \\
tests/test_model_selector.py \\
tests/test_reasoning_selector.py \\
tests/test_review_panel.py \\
tests/test_sessions_command.py \\
tests/test_sessions_startup.py \\
tests/test_settings_modal.py \\
tests/test_startup_queue.py \\
tests/test_status_line.py \\
tests/test_status_line_rendering.py \\
tests/test_tasklist_commands.py \\
tests/test_tasklist_execution.py \\
tests/test_tasklist_navigation.py \\
tests/test_tasklist_polling.py \\
tests/test_token_bar.py \\
tests/test_tui_context_actions.py \\
tests/test_tui_context_visibility.py \\
tests/test_tui_prompt_history.py \\
tests/test_tui_resubmit.py \\
tests/test_tui_session_autoname.py \\
tests/test_tui_session_resume.py \\
tests/test_welcome.py
KEEP (launcher / shared):
`test_api_key_relaunch.py`, `test_avante_config.py`, `test_bifrost_launcher.py`, `test_cli_modes.py`, `test_commit_command.py`, `test_cwd_isolation.py`, `test_dependency_name_derivation.py`, `test_executor_*.py`, `test_github_auth.py`, `test_intellij_config.py`, `test_login_logout_commands.py`, `test_mcp_config.py`, `test_mcp_integration.py`, `test_mcp_launcher.py`, `test_nvim_config.py`, `test_nvim_init_patch.py`, `test_openai_auth.py`, `test_pr_command.py`, `test_rust_acp_install.py`, `test_settings.py`, `test_worktree.py`, `test_zed_config.py`.
Step 4 — Edit `pyproject.toml`
Remove the textual>=0.47.0 line from the dependencies array. Keep httpx>=0.25.0 (used by executor.py) and agent-client-protocol>=0.9.0 (used by mcp_launcher.py).
Current state:
```toml
dependencies = [
"textual>=0.47.0",
"httpx>=0.25.0",
"agent-client-protocol>=0.9.0",
]
```
Target state:
```toml
dependencies = [
"httpx>=0.25.0",
"agent-client-protocol>=0.9.0",
]
```
Then uv lock to refresh uv.lock.
Step 5 — Strip TUI dispatch from `brokk_code/main.py`
Today this file mixes CLI dispatch with the conditional fall-through to the Textual app. Concrete edits:
a) Remove TUI subparsers (lines 887-895)
```python
DELETE:
resume_parser = subparsers.add_parser("resume", help="Resume a specific session")
... (resume_parser arguments through end of resume_parser block)
sessions_parser = subparsers.add_parser("sessions", help="List and switch between sessions")
... (sessions_parser arguments)
```
b) Remove the --resume top-level flag (lines 877-882, the one with dest=\"resume_session\").
c) In _main_dispatch (starts line 1983), remove the BrokkApp lazy-import and start block (~lines 2487-2645). The block currently looks like:
```python
try:
from brokk_code.app import BrokkApp
except ImportError:
print("Error: Could not import BrokkApp. Is app.py missing?")
return 1
resume_session = getattr(args, "resume_session", False)
if args.command == "resume":
...
resume_session = False
elif args.command == "sessions":
...
resume_session = False
... configuration / option parsing ...
app = BrokkApp(
...
resume_session=resume_session,
)
app.run()
```
Replace the entire block with a clean exit when no subcommand was given:
```python
parser.print_help()
return 2
```
(Or parser.error(\"a subcommand is required\") if you prefer the argparse-style error.)
d) Sanity grep: after edits, grep -n 'BrokkApp\\|from brokk_code.app' brokk_code/__main__.py must return zero matches.
Step 6 — Version bump
`brokk_code/init.py`:
```python
version = "0.9.0"
```
Hatch reads this via the [tool.hatch.version] block in pyproject.toml; no other version edit is needed.
Step 7 — Rewrite docs
`README.md` — currently describes the TUI. Rewrite the overview to describe brokk-cli as the launcher for the Brokk Java executor + ACP + bifrost MCP. Keep the install/quickstart sections. Drop screenshots and any reference to chat/context/task panels, sessions, model picker, etc. Add a line: "The interactive Textual TUI was removed in v0.9.0; for the previous TUI use pip install brokk==0.8.10."
`AGENTS.md` / `CLAUDE.md` — currently say "Python (Textual) terminal UI client". Rewrite to: "Python CLI launcher for the Brokk Java executor and related sidecars (ACP, bifrost MCP, editor integrations)." Remove the app.py / widgets/ / styles/ entries from the project structure section. Drop the "Key Dependencies: textual" line. Keep references to executor.py, mcp_launcher.py, mcp_config.py. Keep ACP, install, login/logout sections.
Step 8 — Local validation
```
uv sync --group dev
uv run ruff check
uv run ruff format --check
uv run pytest -q -n auto --no-header
```
Expected: green. Some test_mcp_config.py cases hit https://raw.githubusercontent.com/BrokkAi/brokk/master/claude-plugin/... over the network — this is intentional (see #1).
Step 9 — PR + merge
```
git push -u origin feat/remove-tui
gh pr create --base master --head feat/remove-tui \
--title "feat: remove Textual TUI, keep launcher-only surface" \
--body "Closes #2. See issue for full rationale and file list."
```
Wait for the 3 OS matrix to go green (master is protected with required status checks), then squash-merge into master.
Step 10 — Release v0.9.0
Prerequisite (manual, one-time): on https://pypi.org/manage/project/brokk/settings/publishing/, add a Trusted Publisher with:
- Owner: `BrokkAi`
- Repository: `brokk-cli`
- Workflow: `pypi.yml`
- Environment: `pypi`
Keep the existing `BrokkAi/brokk` publisher in place until the first publish from this repo succeeds.
Then:
```
git checkout master && git pull --ff-only
git tag -a v0.9.0 -m "Remove Textual TUI; launcher-only release"
git push origin v0.9.0
```
Watch `pypi.yml` in the Actions tab. On success, smoke-test from a clean venv:
```
python -m venv /tmp/brokk-smoke && /tmp/brokk-smoke/bin/pip install brokk==0.9.0
/tmp/brokk-smoke/bin/brokk version # prints 0.9.0
/tmp/brokk-smoke/bin/brokk install --help
/tmp/brokk-smoke/bin/brokk acp --help
```
Once green, remove the old `BrokkAi/brokk` trusted publisher from the PyPI dashboard.
After this issue closes
Open the monorepo cleanup issue in BrokkAi/brokk ("Remove brokk-code/, extracted to BrokkAi/brokk-cli") which deletes the now-orphaned brokk-code/ subdirectory and its two CI workflows. That issue is blocked until v0.9.0 publishes successfully.
Context
This repository was extracted from the BrokkAi/brokk monorepo via
git filter-repo --subdirectory-filter brokk-codeto host the launcher / CLI surface of the former "brokk-code" Python project. The interactive Textual TUI is deprecated; brokk-cli continues to ship as the launcher for:brokk acp— headless ACP server over stdio (native Java ACP viamcp_launcher.run_acp_server)brokk bifrost --workspace .— Rust MCP server bootstrapbrokk login/brokk logout/brokk github login|logout|statusbrokk install <editor>— Neovim / Zed / IntelliJ / Codex integration installersbrokk issue create|diagnose|solve,brokk pr create|review,brokk commit,brokk execbrokk mcp,brokk mcp-core,brokk versionThis issue removes every TUI-only file/dependency in a single PR. Total reduction: ~7500 LOC + the
textualruntime dependency.Bumps the version to
0.9.0(breaking: TUI surface removed) and tagsv0.9.0to trigger the first PyPI publish from this repo.Acceptance criteria
pyproject.tomlno longer declarestextualas a runtime dependency.brokk_code/__main__.pyno longer importsBrokkAppor dispatches to the Textual app for any subcommand (or no subcommand).brokk_code/__init__.pybumped to__version__ = \"0.9.0\".README.md,AGENTS.md,CLAUDE.mdrewritten to describe the launcher-only role (no Textual, no widgets/modals/styles, no interactive chat).uv sync --group dev && uv run ruff check && uv run ruff format --check && uv run pytest -q -n autopasses locally.BrokkAi/brokk-cliworkflowpypi.ymlenvpypi(see https://pypi.org/manage/project/brokk/settings/publishing/).v0.9.0pushed;pypi.ymlpublish succeeds;pip install brokk==0.9.0works in a fresh venv.Step 1 — Branch
Step 2 — Delete TUI source files and directories
Confirm with
grep -rln '^from textual\\|^import textual' brokk_code/that no import oftextualremains inbrokk_code/. Today every match is inside the files above.Step 3 — Delete TUI-only tests (29 files)
KEEP (launcher / shared):
`test_api_key_relaunch.py`, `test_avante_config.py`, `test_bifrost_launcher.py`, `test_cli_modes.py`, `test_commit_command.py`, `test_cwd_isolation.py`, `test_dependency_name_derivation.py`, `test_executor_*.py`, `test_github_auth.py`, `test_intellij_config.py`, `test_login_logout_commands.py`, `test_mcp_config.py`, `test_mcp_integration.py`, `test_mcp_launcher.py`, `test_nvim_config.py`, `test_nvim_init_patch.py`, `test_openai_auth.py`, `test_pr_command.py`, `test_rust_acp_install.py`, `test_settings.py`, `test_worktree.py`, `test_zed_config.py`.
Step 4 — Edit `pyproject.toml`
Remove the
textual>=0.47.0line from thedependenciesarray. Keephttpx>=0.25.0(used byexecutor.py) andagent-client-protocol>=0.9.0(used bymcp_launcher.py).Current state:
```toml
dependencies = [
"textual>=0.47.0",
"httpx>=0.25.0",
"agent-client-protocol>=0.9.0",
]
```
Target state:
```toml
dependencies = [
"httpx>=0.25.0",
"agent-client-protocol>=0.9.0",
]
```
Then
uv lockto refreshuv.lock.Step 5 — Strip TUI dispatch from `brokk_code/main.py`
Today this file mixes CLI dispatch with the conditional fall-through to the Textual app. Concrete edits:
a) Remove TUI subparsers (lines 887-895)
```python
DELETE:
resume_parser = subparsers.add_parser("resume", help="Resume a specific session")
... (resume_parser arguments through end of resume_parser block)
sessions_parser = subparsers.add_parser("sessions", help="List and switch between sessions")
... (sessions_parser arguments)
```
b) Remove the
--resumetop-level flag (lines 877-882, the one withdest=\"resume_session\").c) In
_main_dispatch(starts line 1983), remove the BrokkApp lazy-import and start block (~lines 2487-2645). The block currently looks like:```python
try:
from brokk_code.app import BrokkApp
except ImportError:
print("Error: Could not import BrokkApp. Is app.py missing?")
return 1
resume_session = getattr(args, "resume_session", False)
if args.command == "resume":
...
resume_session = False
elif args.command == "sessions":
...
resume_session = False
... configuration / option parsing ...
app = BrokkApp(
...
resume_session=resume_session,
)
app.run()
```
Replace the entire block with a clean exit when no subcommand was given:
```python
parser.print_help()
return 2
```
(Or
parser.error(\"a subcommand is required\")if you prefer the argparse-style error.)d) Sanity grep: after edits,
grep -n 'BrokkApp\\|from brokk_code.app' brokk_code/__main__.pymust return zero matches.Step 6 — Version bump
`brokk_code/init.py`:
```python
version = "0.9.0"
```
Hatch reads this via the
[tool.hatch.version]block inpyproject.toml; no other version edit is needed.Step 7 — Rewrite docs
`README.md` — currently describes the TUI. Rewrite the overview to describe brokk-cli as the launcher for the Brokk Java executor + ACP + bifrost MCP. Keep the install/quickstart sections. Drop screenshots and any reference to chat/context/task panels, sessions, model picker, etc. Add a line: "The interactive Textual TUI was removed in v0.9.0; for the previous TUI use
pip install brokk==0.8.10."`AGENTS.md` / `CLAUDE.md` — currently say "Python (Textual) terminal UI client". Rewrite to: "Python CLI launcher for the Brokk Java executor and related sidecars (ACP, bifrost MCP, editor integrations)." Remove the
app.py/widgets//styles/entries from the project structure section. Drop the "Key Dependencies: textual" line. Keep references toexecutor.py,mcp_launcher.py,mcp_config.py. Keep ACP, install, login/logout sections.Step 8 — Local validation
```
uv sync --group dev
uv run ruff check
uv run ruff format --check
uv run pytest -q -n auto --no-header
```
Expected: green. Some
test_mcp_config.pycases hithttps://raw.githubusercontent.com/BrokkAi/brokk/master/claude-plugin/...over the network — this is intentional (see #1).Step 9 — PR + merge
```
git push -u origin feat/remove-tui
gh pr create --base master --head feat/remove-tui \
--title "feat: remove Textual TUI, keep launcher-only surface" \
--body "Closes #2. See issue for full rationale and file list."
```
Wait for the 3 OS matrix to go green (master is protected with required status checks), then squash-merge into master.
Step 10 — Release v0.9.0
Prerequisite (manual, one-time): on https://pypi.org/manage/project/brokk/settings/publishing/, add a Trusted Publisher with:
Keep the existing `BrokkAi/brokk` publisher in place until the first publish from this repo succeeds.
Then:
```
git checkout master && git pull --ff-only
git tag -a v0.9.0 -m "Remove Textual TUI; launcher-only release"
git push origin v0.9.0
```
Watch `pypi.yml` in the Actions tab. On success, smoke-test from a clean venv:
```
python -m venv /tmp/brokk-smoke && /tmp/brokk-smoke/bin/pip install brokk==0.9.0
/tmp/brokk-smoke/bin/brokk version # prints 0.9.0
/tmp/brokk-smoke/bin/brokk install --help
/tmp/brokk-smoke/bin/brokk acp --help
```
Once green, remove the old `BrokkAi/brokk` trusted publisher from the PyPI dashboard.
After this issue closes
Open the monorepo cleanup issue in BrokkAi/brokk ("Remove brokk-code/, extracted to BrokkAi/brokk-cli") which deletes the now-orphaned brokk-code/ subdirectory and its two CI workflows. That issue is blocked until v0.9.0 publishes successfully.