Skip to content

goose tui#5831

Closed
tlongwell-block wants to merge 163 commits intomainfrom
tui_gem
Closed

goose tui#5831
tlongwell-block wants to merge 163 commits intomainfrom
tui_gem

Conversation

@tlongwell-block
Copy link
Copy Markdown
Collaborator

@tlongwell-block tlongwell-block commented Nov 20, 2025

This PR introduces a terminal user interface for goose, along with a first-party Rust client library for goose-server.

TUI Features

A lightweight, keyboard-driven interface for goose that runs entirely in your terminal:

  • Embedded server: No separate processes—goose-server runs in-process
  • Rich rendering: Markdown support with syntax-highlighted code blocks
  • Tool inspection: View available tools and their schemas. Create slash commands to run tools
  • Vim-style navigation: Normal/Editing/Visual modes with familiar keybindings
  • Session management: Resume previous conversations or start fresh. Support conversation forking.
  • Live configuration: Switch providers, models, and extensions without restarting
  • Smart context: Automatic project analysis on new sessions
  • Copy mode: Select text to copy with keyboard+mouse or copy entire message/tool response to clipboard
  • Themes: Beautiful built-in themes and support for custom themes defined in your goose config
  • Multiple modes: Full TUI, lightweight CLI mode, server only, or headless for automation

The TUI provides a fast, distraction-free way to interact with goose for developers who prefer staying in the terminal.

goose-client

A reusable Rust client library for goose-server that provides:

  • Type-safe API bindings for all goose-server endpoints
  • SSE streaming for real-time message events
  • Async/await support with tokio
  • Minimal dependencies (reqwest, serde)

Having a first-party Rust client offers several benefits:

  1. Type safety: Compile-time guarantees that client/server contracts match
  2. Reference implementation: Demonstrates best practices for building goose-server clients
  3. Ecosystem growth: Makes it easier for Rust developers to build custom goose interfaces

The client is designed to be lightweight and focused—it handles HTTP communication and serialization, while leaving UI concerns to consumers like goose-tui.

goose_logo_tui tui_screen2 retro

@tlongwell-block tlongwell-block changed the title goose tui draft goose tui draft (do not review) Nov 20, 2025
@michaelneale
Copy link
Copy Markdown
Collaborator

I love this. We need this @DOsinga !

@DOsinga
Copy link
Copy Markdown
Collaborator

DOsinga commented Nov 21, 2025

love this too. my one question is, do we want to do this in rust? I have two reasons why we should consider typescript. one, I think the TUI support in typescript is better and it is just quicker to develop. the other is that from a platform perspective it would just be neat to have two client implementations that both use the goosed protocol and show to the community how that works and invite them to build more.

@tlongwell-block
Copy link
Copy Markdown
Collaborator Author

tlongwell-block commented Nov 21, 2025

love this too. my one question is, do we want to do this in rust? I have two reasons why we should consider typescript. one, I think the TUI support in typescript is better and it is just quicker to develop. the other is that from a platform perspective it would just be neat to have two client implementations that both use the goosed protocol and show to the community how that works and invite them to build more.

This does use the goosed protocol (check out crates/goose-tui/src/client.rs)

And... I did look at typescript, too. But it is slightly messier. By using rust, we get to reuse a lot from the rest of goose, and embed goose-server directly without having to ship it as a separate file

ratatui is definitely not as easy to make aesthetic and responsive, though

@codefromthecrypt
Copy link
Copy Markdown
Collaborator

@tlongwell-block probably doesn't apply to here but in IDEs like jetbrains claude has intense flickering. Not sure we've anything in common with it, but could be worth a review to see if there's anything in pretty tui here that could result in flickering anthropics/claude-code#769

- Resolved conflicts in agent.rs, platform/mod.rs, and Cargo.lock
- Added pub visibility and Serialize derives to structs needed by goose-client
- Updated goose-client to use new fields (extension_overrides, context_limit, request_params)
- Fixed reducer_test.rs to include task field in CallToolRequestParam
- Preserved android support in platform/mod.rs from tui_gem branch
* origin/main:
  Fix GCP Vertex AI global endpoint support for Gemini 3 models (#6187)
  fix: macOS keychain infinite prompt loop    (#6620)
  chore: reduce duplicate or unused cargo deps (#6630)
  feat: codex subscription support (#6600)
  smoke test allow pass for flaky providers (#6638)
  feat: Add built-in skill for goose documentation reference (#6534)
  Native images (#6619)
  docs: ml-based prompt injection detection (#6627)
  Strip the audience for compacting (#6646)
  chore(release): release version 1.21.0 (minor) (#6634)
  add collapsable chat nav (#6649)
  fix: capitalize Rust in CONTRIBUTING.md (#6640)
  chore(deps): bump lodash from 4.17.21 to 4.17.23 in /ui/desktop (#6623)
  Vibe mcp apps (#6569)
  Add session forking capability (#5882)
  chore(deps): bump lodash from 4.17.21 to 4.17.23 in /documentation (#6624)
  fix(docs): use named import for globby v13 (#6639)
  PR Code Review (#6043)
  fix(docs): use dynamic import for globby ESM module (#6636)

# Conflicts:
#	Cargo.lock
#	crates/goose-server/src/routes/session.rs
@taniacryptid
Copy link
Copy Markdown
Collaborator

taniacryptid commented Jan 23, 2026

Posting @tlongwell-block's update in context for hands-on review 🙏

Hi folks - would really appreciate some eyes (and hands-on time). This adds a goose-tui binary that’s a nice terminal experience (and it also has a plain --cli mode and a server only mode). A big upside is that it lets us move everything onto goose-server.

Today, goose-cli has its own backend setup. This PR is a path to having every goose UI share the same backend machinery and behavior.

We can merge it as goose-tui first, ask people to try it for a few weeks, iterate on feedback, and then over the next couple months start deprecating goose-cli and the standalone goose-server/goosed binary once we’re confident it’s solid and we’re not breaking anything anyone cares about.

Or maybe we don't want a TUI for goose and we don't want to mess with the goose cli that's already working fine, I'd just like to close out or move forward on this PR.

@block/goose-core-maintainers @block/goose-core-maintainers

@alexhancock
Copy link
Copy Markdown
Collaborator

alexhancock commented Jan 25, 2026

@taniandjerry @tlongwell-block We definitely need a new terminal UX!

I think we should have a chat about the future of the cli. As part of #6642 I prototyped an InkJS based TUI that was incredibly powerful, and implemented in a very small number of files due to expressiveness of TS and the ACP interface.

main...alexhancock/goosed-acp-and-new-cli#diff-0c954f5db4ecda500f284985d4cad2bc18bd3d3b52b2efff237dad38ea7a1e18

I built a prototype that had a single agent mode as well as an orchestrator mode that could spin up multiple agents each working on worktrees. I came away feeling like this is definitely the way forward for new clients, including our own.

Let's discuss next week?

cc @DOsinga

Resolves unicode-width dependency conflict between pctx (needs ^0.2.1 via
deno/swc) and ratatui 0.29 (pins =0.2.0) by:

- Using tui-textarea from PR #122 (ratatui 0.30 support) pinned to commit
  48792febd9d454fefdd869de0e75849cad6e6007
  rhysd/tui-textarea#122
- Upgrading goose-tui to ratatui 0.30, crossterm 0.29, ansi-to-tui 8.0.1
- Fixing type ambiguity in chat.rs/info.rs (multiple unicode-width versions)
- Updating tests for CallToolRequestParams API change (added meta field)
* origin/main: (107 commits)
  feat: Allow overriding default bat themes using environment variables (#7140)
  Make the system prompt smaller (#6991)
  Pre release script (#7145)
  Spelling (#7137)
  feat(mcp): upgrade rmcp to 0.15.0 and advertise MCP Apps UI extension capability (#6927)
  fix: ensure assistant messages with tool_calls include content field (#7076)
  fix(canonical): handle gcp_vertex_ai model mapping correctly (#6836)
  Group dependencies in root Cargo.toml (#6948)
  refactor: updated elevenLabs API module and `remove button` UX (#6781)
  fix: we were missing content from langfuse traces (#7135)
  docs: update username in authors.yml (#7132)
  fix extension selector syncing issues (#7133)
  fix(acp): per-session Agent for model isolation and load_session restore (#7115)
  fix(claude-code): defensive coding improvements for model switching (#7131)
  feat(claude-code): dynamic model listing and mid-session model switching (#7120)
  Inline worklet source (#7128)
  [docs] One shot prompting is dead - Blog Post (#7113)
  fix: correct spelling of Debbie O'Brien's name in authors.yml (#7127)
  docs: GCP Vertex AI org policy filtering & update OnboardingProviderSetup component (#7125)
  feat: replace subagent and skills with unified summon extension (#6964)
  ...

# Conflicts:
#	Cargo.lock
#	Cargo.toml
* origin/main:
  docs: playwright CLI skill tutorial (#7261)
  install node in goose dir (#7220)
  fix: relax test_basic_response assertion for providers returning reasoning_content (#7249)
  fix: handle reasoning_content for Kimi/thinking models (#7252)
  feat: sandboxing for macos (#7197)
  fix(otel): use monotonic_counter prefix and support temporality env var (#7234)
  Streaming markdown (#7233)
  Improve compaction messages to enable better post-compaction agent behavior (#7259)
  fix: avoid shell-escaping special characters except quotes (#7242)
  fix: use dynamic port for Tetrate auth callback server (#7228)
  docs: removing LLM Usage admonitions (#7227)
  feat(otel): respect standard OTel env vars for exporter selection (#7144)
  fix: fork session (#7219)
  Bump version numbers for 1.24.0 release (#7214)
  Move platform extensions into their own folder (#7210)
  fix: ignore deprecated skills extension (#7139)

# Conflicts:
#	Cargo.lock
#	Cargo.toml
* origin/main: (62 commits)
  Docs: claude code uses stream-json (#7358)
  Improve link confirmation modal (#7333)
  fix(ci): deflake smoke tests for Google models (#7344)
  feat: add Cerebras provider support (#7339)
  fix: skip whitespace-only text blocks in Anthropic message (#7343)
  fix(goose-acp): heap allocations (#7322)
  Remove trailing space from links (#7156)
  fix: detect low balance and prompt for top up (#7166)
  feat(apps): add support for MCP apps to sample (#7039)
  Typescript SDK for ACP extension methods (#7319)
  chore: upgrade to rmcp 0.16.0 (#7274)
  docs: add monitoring subagent activity section (#7323)
  docs: document Desktop UI recipe editing for model/provider and extensions (#7327)
  docs: add CLAUDE_THINKING_BUDGET and CLAUDE_THINKING_ENABLED environm… (#7330)
  fix: display 'Code Mode' instead of 'code_execution' in CLI (#7321)
  docs: add Permission Policy documentation for MCP Apps (#7325)
  update RPI plan prompt (#7326)
  docs: add CLI syntax highlighting theme customization (#7324)
  fix(cli): replace shell-based update with native Rust implementation (#7148)
  docs: rename Code Execution extension to Code Mode extension (#7316)
  ...

# Conflicts:
#	crates/goose-server/src/main.rs
Replace the tui-textarea dependency (via madsmao fork) with
ratatui-textarea from the official ratatui org's fork.

The upstream ratatui/ratatui-textarea main branch only supports
ratatui 0.29, which conflicts with bat's unicode-width ^0.2.1
requirement. Using dotdash's PR #3 branch (pinned to commit sha)
which adds ratatui 0.30 support via the split ratatui sub-crates.

Changes:
- Remove workspace [patch.crates-io] for tui-textarea
- Switch goose-tui dep from tui-textarea to ratatui-textarea
- Update all imports from tui_textarea to ratatui_textarea

Ref: ratatui/ratatui-textarea#3
* origin/main: (21 commits)
  feat(ui): show token counts directly for "free" providers (#7383)
  Update creator note (#7384)
  Remove display_name from local model API and use model ID everywhere (#7382)
  fix(summon): stop MOIM from telling models to sleep while waiting for tasks (#7377)
  Completely pointless ascii art (#7329)
  feat: add Neighborhood extension to the Extensions Library (#7328)
  feat: computer controller overhaul, adding peekaboo (#7342)
  Add blog post: Gastown Explained: How to Use Goosetown for Parallel Agentic Engineering (#7372)
  docs: type-to-search goose configure lists (#7371)
  docs: search conversation history (#7370)
  fix: stderr noise (#7346)
  chore(deps): bump hono from 4.11.9 to 4.12.0 in /ui/desktop (#7369)
  Include 3rd-party license copy for JavaScript/CSS minified files (#7352)
  docs for reasoning env var (#7367)
  docs: update skills detail page to reference Goose Summon extension (#7350)
  fix(apps): restore MCP app sampling support reverted by #6933 (#7366)
  feat: TUI client of goose-acp (#7362)
  docs: agent variable (#7365)
  docs: pass env vars to shell (#7361)
  docs: update sandbox topic (#7336)
  ...

# Conflicts:
#	Cargo.lock
@albina-popova
Copy link
Copy Markdown
Contributor

@DOsinga is there any chance this PR would be merged soon? Would much appreciate that.

* origin/main:
  doc: groq models (#7404)
  Client settings (#7381)
  Fix settings tabs getting cut off in narrow windows (#7379)
  docs: voice dictation updates (#7396)
  [docs] Add Excalidraw MCP App Tutorial (#7401)
  Post release checklist as a comment on release PRs (#7307)
  unique api key (#7391)
  fix: use correct colors for download progress bar (#7390)
  Add local model settings access from bottom bar model menu (#7378)
  Change Recipe Security Scanner API key (#7387)
  switch Ask AI Discord bot from openrouter to anthropic (#7386)
* origin/main:
  feat: expose context window utilization to agent via MOIM (#7418)
  Small model naming (#7394)
  chore(deps): bump ajv in /documentation (#7416)
@tlongwell-block
Copy link
Copy Markdown
Collaborator Author

Will contribute to https://github.com/block/goose/tree/main/ui/acp instead

* origin/main: (107 commits)
  Merge platform/builtin extensions (#7630)
  Clean up stale references to removed components (#7644)
  fix: scope empty session reuse to current window to prevent session mixing (#7602)
  fix: prevent abort in local inference  (#7633)
  Revert git patch for llama-cpp-2 (#7642)
  docs: update recipe usage step to reflect auto-submit behavior (#7639)
  docs: add guide for customizing the sidebar (#7638)
  docs: update Claude Code approve behavior and model list in cli-providers guide (#7448)
  fix: restore provider and extensions for LRU-evicted sessions (#7616)
  Restore goosed logging (#7622)
  feat: return structured {stdout, stderr} from shell tool with output schema (#7604)
  Improve custom provider creation experience (#7541)
  fix(scheduler): schedules added via CLI showing up in UI (#7594)
  chore: openai reasoning model cleanup (#7529)
  chore(deps): bump hono from 4.12.1 to 4.12.3 in /evals/open-model-gym/mcp-harness (#7585)
  chore(deps): bump minimatch from 10.1.1 to 10.2.3 in /evals/open-model-gym/suite (#7498)
  chore(deps): bump swiper from 11.2.10 to 12.1.2 in /documentation (#7368)
  Better network failure error & antrhopic retry (#7595)
  feat: make the text bar persistent and add a queue for messages (#7560)
  fix: outdated clippy command in goosehints (#7590)
  ...

# Conflicts:
#	Cargo.lock
#	Cargo.toml
#	crates/goose-server/src/commands/agent.rs
#	crates/goose-server/src/main.rs
#	crates/goose-server/src/routes/reply.rs
* origin/main:
  fix(shell): replace global static output buffer with per-instance TempDir (#7632)
  opt: remove timestamped config file backup (#7618)
  chore(deps): bump @hono/node-server from 1.19.9 to 1.19.10 in /ui/desktop (#7662)
  chore(deps): bump hono from 4.12.3 to 4.12.5 in /evals/open-model-gym/mcp-harness (#7661)
  chore(deps): bump hono from 4.12.2 to 4.12.5 in /ui/desktop (#7660)
  fix: resolve parameters in initial message with autosubmit (#7659)
  fix: this should not be blocked (#7656)
  Relax the assertion for the model list ACP test (#7653)
  fix: add analyzer extension in recipe to maintain backwards compatibility  (#7652)
  docs: add GOOSE_INPUT_LIMIT environment variable documentation (#7299)
…rd compatibility

Added to goose run:
- Extension loading: --with-extension, --with-streamable-http-extension, --with-builtin, --no-profile
- Session management: --name, --session-id, --resume, --no-session, --interactive
- Safety limits: --debug, --max-tool-repetitions, --max-turns
- Output: --output-format (text/json/stream-json)
- Recipe: --sub-recipe, --explain, --render-recipe

Added to recipe subcommand: deeplink, open (with params)
Added to schedule subcommand: services-status, services-stop (deprecated compat)

Extension parsing functions ported from goose-cli session module.
Headless mode now supports json and stream-json output formats.
configure_session supports --no-profile and CLI extension loading.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants