Markdown syntax highlighting not working in Terminal.app on macOS
Describe the bug
goose CLI does not display markdown syntax highlighting when running in Terminal.app on macOS, despite the terminal supporting full color and formatting capabilities. All markdown content is rendered as plain text without colors, bold formatting, or syntax highlighting for code blocks.
A clear and concise description of what the bug is.
Expected Behavior
When goose responds with markdown content, it should display:
- ✅ Colored headers (e.g.,
# Headerin bright color) - ✅ Bold text (e.g.,
**bold**rendered as bold) - ✅ Syntax-highlighted code blocks (e.g., Rust code with proper colors)
- ✅ Formatted lists, quotes, and links
Actual Behavior
All markdown content is rendered as plain text:
- ❌ Headers appear as regular text with
#symbols - ❌ Bold markers
**text**are shown literally - ❌ Code blocks have no syntax highlighting
- ❌ No colors or formatting applied
However, I did find that the syntax highlighting shows in other apps such as Cursor's terminal or ghostty
ghostty
Environment
- OS: macOS (Terminal.app)
- goose version: 1.6.0
- Terminal: Terminal.app (default macOS terminal)
- Shell: bash/zsh
- TERM:
xterm-256color
I asked goose, and it suggested that this could be the root cause
Root Cause
The issue is in crates/goose-cli/src/session/output.rs in the print_markdown() function:
fn print_markdown(content: &str, theme: Theme) {
if std::io::stdout().is_terminal() { // ← Too strict!
// bat syntax highlighting
} else {
print!("{}", content); // ← Falls back to plain text
}
}
The std::io::stdout().is_terminal() check is too restrictive and fails in many legitimate terminal environments, including:
- IDE integrated terminals
- Terminal multiplexers (tmux, screen)
- Some macOS Terminal.app configurations
- SSH sessions
- Process managers/wrappers
Technical Details
- goose uses the
batcrate (v0.24.0) for markdown syntax highlighting - The
batlibrary works correctly and can render colors - The issue is purely in the terminal detection logic
- When TTY detection fails, goose falls back to plain text instead of attempting colored output
Update
@DOsinga mentioned how this issue should be addressed. Pasted below: We do not want = if we go through a pipe, we will now be using colors. What we want = to use colors when we are displaying directly to the screen. When the output is redirected, you want non-ansi code because you are probably going to programmatically process it.
.take
Hi, I’d like to work on this issue!
Thanks for taking this issue! Let us know if you have any questions!
Hi @bunnypowers ! Let us know if you have any questions <3
.take
Thanks for taking this issue! Let us know if you have any questions!
Wanted to check in and see if you had a chance at this, @ConstantTime ! Thank you for your work so far, looking forward to your next open PR for this <3
Wanted to check in and see if you had a chance at this, @ConstantTime ! Thank you for your work so far, looking forward to your next open PR for this <3
Hey @taniandjerry I should have something out here by end of this week. Turns out this is slightly more time taking than I thought it would be
No worries, thank you for the update! @ConstantTime
Opened up a new PR for this^
Douwe left you comments on it! thank you for contributing.
As I mentioned in your linked PR #5393 , @DOsinga left some comments on it on the direction for a fix for this. Since the issue won't be able to be addressed in time for review for Hacktoberfest, I've removed the hacktoberfest label. I've also updated this issue with his comment on the intended direction for a fix for this.