goose tui
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:
- Type safety: Compile-time guarantees that client/server contracts match
- Reference implementation: Demonstrates best practices for building goose-server clients
- 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.
I love this. We need this @DOsinga !
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.
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
yeah building on goosed makes sense, but I didn think about a non rust one, it does mean more distirbution hassle but then developers only are using this, so yeah https://github.com/sst/opentui or even using the codex (opensource) code as a client could be doable (or adapting/lifting) - thoughts @tlongwell-block ? rattatui I always found challenging. I guess downside is people need node installed?
yeah building on goosed makes sense, but I didn think about a non rust one, it does mean more distirbution hassle but then developers only are using this, so yeah https://github.com/sst/opentui or even using the codex (opensource) code as a client could be doable (or adapting/lifting) - thoughts @tlongwell-block ? rattatui I always found challenging. I guess downside is people need node installed?
I'm still playing with it right now, but I'm surprised at how nice it is. Will have a more informed opinion by the end of the day, I think.
Also, I think there's a really good opportunity here wrt code reuse. I'm going to refactor this a little today to make this work more easily accessible to other projects.
And isn't there something kind of romantic about rust?
I broke the client bits into crates/goose-client
I think having a first party rust client that uses the actual structs/enums/etc from goose/goose-server adds a lot of value to the project. What do you think, @DOsinga?
I am liking this more now - so the goose-client exists mostly to expose things, I wonder if we can simplify that (ie not have another module), also we could drop the main cli so that the goose-tui becomes the one goose binary (and perhaps we can unify the bianry so goose/goosed are same thing - just default is tui?)
Anyway, can dive into those details shortly - but so far looking good, and yeah, if we are to do a TUI, I think it makes sense to do it in rust @DOsinga for now, mostly as I looked around, didn't see any suitable ready to go TUIs in ts/js (certainly not that arent' really just libraries and would take a fair bit of work - but that may happen one day, but for now, its really just apis for TUIs no matter what, so ts, or rust, have to pick one?)
using this as a daily:
not sure what causes it to keep that persistent message for "clippy" there? anytime it is working, the spinner is next to it (must be some most recent status message?)
(sorry for screen caps)
I guess that is showing a command, but not sure what is meant to be in body of the dev tool (is empty in that case)
I am liking this more now - so the goose-client exists mostly to expose things, I wonder if we can simplify that (ie not have another module), also we could drop the main cli so that the goose-tui becomes the one goose binary (and perhaps we can unify the bianry so goose/goosed are same thing - just default is tui?)
We can absolutely move goose-client back into the tui crate. (That's how it was originally.)
Just a matter of taste. I thought it was independent enough to show a good example of a goose-server client, but it isn't particularly useful as its own crate.
using this as a daily:
not sure what causes it to keep that persistent message for "clippy" there? anytime it is working, the spinner is next to it (must be some most recent status message?)
That is the current item on the todo list goose is working on. Hit Ctrl+T to see the full list. I am going to improve its todo list usage a bit to make this status line more useful
I guess that is showing a command, but not sure what is meant to be in body of the dev tool (is empty in that case)
The yellow line ( > developer__shell (args hidden)) is the tool call, which you can highlight and click (or hit Enter) on to view the full tool call.
The box below that is the tool response. In this case, it appears the tool didn't return any results
As a "goose power user", I wanted to be able to see both in full when I chose to
@tlongwell-block ok that makes sense, as long as deliberate. I idd think it odd it kept that there, but that just means it is still in todo I guess? (which is odd itself, but not on the part of the TUI).
I would love to see this in the goose-cli crate, vs goose-tui - if it was up to me? (I wouldn't want to keep old CLI as well as this, but maybe it is a cut over? but don't want to maintain 2)
cc @jamadeo @DOsinga would love your take, would really like this to be default goose command vs goose-tui I think (and we still have to support recipes, run and all the other cli constructs somehow) and then eventually retire the old goose-cli code? (and could also perhaps combine some of this with goose-server?) but could be in a phased approach (the way it is now, is a new binary, which means people wont' really discover or use it)
cc @jamadeo @DOsinga would love your take, would really like this to be default goose command vs goose-tui I think (and we still have to support recipes, run and all the other cli constructs somehow) and then eventually retire the old goose-cli code? (and could also perhaps combine some of this with goose-server?) but could be in a phased approach (the way it is now, is a new binary, which means people wont' really discover or use it)
yeah, I'm all for thinking ahead and the CLI is a bit old in tooth. but then again, I am not sure that doing product development by PR is the right way in this case. Personally I don't think Rust would be my first choice for a user interface, whether GUI or TUI. I know a lot of work went into this already, but would it be an idea to take a step back and post a discussion about where we want to go with this first?
yeah, I'm all for thinking ahead and the CLI is a bit old in tooth. but then again, I am not sure that doing product development by PR is the right way in this case. Personally I don't think Rust would be my first choice for a user interface, whether GUI or TUI. I know a lot of work went into this already, but would it be an idea to take a step back and post a discussion about where we want to go with this first?
I thought the exact same thing wrt rust for frontend work. I did full working mockups in ink and ratatui. Besides some initial teething issues, I ended up greatly preferring ratatui and the ability to pull in from the goose codebase directly where needed.
I don't know how folks feel about a TUI for goose in general, though. It may not be the right direction.
I ended up working on this after spending a lot of time with gemini-cli TUI in order to test gemini 3 and found there were strong points that I wanted in my goose experience that I couldn't get with the goose cli.
@DOsinga @tlongwell-block I'm not sure practically how a TUI which is not in rust would work with goose - would mean need to install goose via npm (for example) instead of a monolithic binary as of now (pros/cons?) - and doesn't there always need to be a "cli" like experience in goose (and the cli is getting a little dated) anyway? Disagree that this a bad way to explore "product by PR" in this specific case (well assuming it isn't backbraking manual! sorry if it was @tlongwell-block!) - I tried to find other TUIs I liked and other than actually driving it, it is hard to try them out. There really isn't a way to mock/design things like this other than trying it out IMO.
could move this to a discussion to continue?
- do we want TUI at all - is it a passing fashion?
- do it in rust, or bring along another dependency if people want cli
- update cli in place
-
whether GUI or TUI: I wouldn't at all group those together for chosing rust or not (I am thinking just replacement for goose-cli but perhaps others have bigger things in mind?)
- move to the @goose terminal enhancement and deprecate goose-cli crate (!)
many good options (I will open this as a discussion, seems mixed engagement there but it is picking up).
Chatting in https://github.com/block/goose/discussions/5958
Tested locally and works well! UI looks really good also.
I'm not too familiar with TUIs so a couple things that stick out to me:
- mouse support for highlighting and copying text would be nice
- it pops the message details everywhere I click with the mouse which feels a bit strange/annoying to me, maybe the click trigger could be localized to the message itself or an icon at the top for more details?
Tested locally and works well! UI looks really good also.
I'm not too familiar with TUIs so a couple things that stick out to me:
- mouse support for highlighting and copying text would be nice
- it pops the message details everywhere I click with the mouse which feels a bit strange/annoying to me, maybe the click trigger could be localized to the message itself or an icon at the top for more details?
Thanks for testing this out!
Mouse support is there, but requires hitting Ctrl+S to shift into copy mode first. Aside from that, pressing 'c' when viewing the details popup on a message lets you copy the whole message. This setup is at par with other TUIs afaik, but I am still working on making this better. It should be easier.
Yes, I can see that clicking behavior not making sense. It's doing the same thing as enter and opening the highlighted message (which is normally the last one unless you scroll back). Let me fix this. No one would think clicking would open the highlighted message instead of whatever they're clicking on.
Something else to think about here: since this is a pure rust implementation, we are able to bundle the actual goose-server for the TUI to use.
Which means we don't need to build a separate goose-server binary to ship with the desktop UI if we adopt the TUI.
The TUI binary can do goose-tui server already to run goose-server without a UI, which the desktop app can use.
So... anyone who would install the desktop UI gets a TUI for free, essentially. With very little added weight to the distribution.
not sure what causes it to keep that persistent message for "clippy" there? anytime it is working, the spinner is next to it (must be some most recent status message?)
I guess that is showing a command, but not sure what is meant to be in body of the dev tool (is empty in that case)