Terminal UI
UI building blocks
ChatUI— centralises colours, icons, borders, and separators.ToolResultPresenter— renders tool calls, results, diffs, and markdown.MessageService— uses UI helpers to show processing states and assistant headers.
Palette and symbols
src/chat/ui/ChatUI.ts
export const UI = {
Colors: {
BORDER: chalk.hex('#4B5563'),
ACCENT: chalk.hex('#38BDF8'),
ACCENT_BRIGHT: chalk.hex('#7DD3FC'),
SECONDARY: chalk.hex('#E5E7EB'),
MUTED: chalk.hex('#9CA3AF'),
TOOL: chalk.hex('#A855F7'),
SUCCESS: chalk.hex('#34D399'),
ERROR: chalk.hex('#F87171'),
WARNING: chalk.hex('#FBBF24'),
DIFF_ADD: chalk.hex('#22C55E'),
DIFF_REMOVE: chalk.hex('#F87171'),
DIFF_CONTEXT: chalk.hex('#94A3B8'),
},
Icons: {
ASSISTANT: '🤖',
USER: '',
PROCESSING: '⟳',
CHANGES: '',
MARKDOWN: '',
SUCCESS: '✔',
ERROR: '✖',
WARNING: '⚠',
PREVIEW: '👁',
},
Separators: {
THIN: chalk.hex('#4B5563')('─'.repeat(78)),
},
indent: (text: string, spaces: number) =>
text
.split('\n')
.map((line) => ' '.repeat(spaces) + line)
.join('\n'),
}
- Colours match the rest of the CLI, making it easy to modify themes in one place.
- Icons use Nerd Font glyphs where possible; adjust to your font preferences.
Frames and headers
src/chat/MessageService.ts
const displayProcessing = () =>
Console.log(
UI.Colors.BORDER('\n╭─ ') +
UI.Colors.TOOL(`${UI.Icons.PROCESSING} `) +
UI.Colors.MUTED('Processing...') +
UI.Colors.BORDER(` ${'─'.repeat(62)}`),
)
const displayAssistantHeader = () =>
Console.log(
'\n' +
UI.Colors.BORDER('╭─ ') +
UI.Colors.ACCENT(`${UI.Icons.ASSISTANT} `) +
UI.Colors.ACCENT_BRIGHT('Assistant') +
' ' +
UI.Colors.BORDER('─'.repeat(66)),
)
const displayComplete = () => Console.log(`${UI.Colors.BORDER(`╰${'─'.repeat(78)}`)}\n`)
- Frames bookend each response so tool output appears inside a consistent box.
- You can swap glyphs or adjust widths without touching other modules.
Tool presenters
src/chat/ui/ToolResultPresenter.ts
export const displayToolResult = (toolName: string, result: ToolResult): void => {
const summary = formatToolResultSummary(result, toolName)
const icon = result?.error ? UI.Icons.ERROR : UI.Icons.SUCCESS
const color = result?.error ? UI.Colors.ERROR : UI.Colors.SUCCESS
console.log(
UI.Colors.BORDER(' ') +
color(`${icon} `) +
(result?.error ? UI.Colors.ERROR(summary) : UI.Colors.SECONDARY(summary)),
)
displayDetailedToolResult(result, toolName)
process.stdout.write('\n')
}
formatToolResultSummarycondenses the payload into a single status line.- Follow-up helpers (
displayWriteFileDiff,displayMarkdownMetadata, etc.) only run when applicable.
Extending the UI
- Add a new presenter for custom tools to maintain consistent styling.
- Adjust
UI.Separatorsorindenthelpers to match your terminal width. - Wrap experimental output (e.g., streaming logs) in the same border style to keep the layout cohesive.
Source
src/chat/ui/ChatUI.tssrc/chat/ui/ToolResultPresenter.tssrc/chat/MessageService.ts