diff --git a/packages/coding-agent/docs/tui.md b/packages/coding-agent/docs/tui.md index c3b31204..c8ff3554 100644 --- a/packages/coding-agent/docs/tui.md +++ b/packages/coding-agent/docs/tui.md @@ -257,7 +257,7 @@ md.setText("Updated markdown"); ### Image -Renders images in supported terminals (Kitty, iTerm2, Ghostty, WezTerm). +Renders images in supported terminals (Kitty, iTerm2, Ghostty, WezTerm, Warp). ```typescript const image = new Image( diff --git a/packages/tui/src/terminal-image.ts b/packages/tui/src/terminal-image.ts index d7012c1d..8854a86a 100644 --- a/packages/tui/src/terminal-image.ts +++ b/packages/tui/src/terminal-image.ts @@ -92,6 +92,11 @@ export function detectCapabilities(tmuxForwardsHyperlink: () => boolean = probeT return { images: "kitty", trueColor: true, hyperlinks: true }; } + // Warp supports the Kitty graphics protocol and OSC 8 hyperlinks. + if (termProgram === "warpterminal" || process.env.WARP_SESSION_ID || process.env.WARP_TERMINAL_SESSION_UUID) { + return { images: "kitty", trueColor: true, hyperlinks: true }; + } + if (process.env.ITERM_SESSION_ID || termProgram === "iterm.app") { return { images: "iterm2", trueColor: true, hyperlinks: true }; } diff --git a/packages/tui/test/terminal-image.test.ts b/packages/tui/test/terminal-image.test.ts index 4e9a3fc9..cc7e01e5 100644 --- a/packages/tui/test/terminal-image.test.ts +++ b/packages/tui/test/terminal-image.test.ts @@ -30,6 +30,8 @@ const ENV_KEYS = [ "ITERM_SESSION_ID", "WT_SESSION", "CMUX_WORKSPACE_ID", + "WARP_SESSION_ID", + "WARP_TERMINAL_SESSION_UUID", ] as const; function withEnv(overrides: Record, fn: () => void): void { @@ -271,6 +273,48 @@ describe("detectCapabilities", () => { }); }); + it("enables images and hyperlinks for Warp via TERM_PROGRAM", () => { + withEnv({ TERM_PROGRAM: "WarpTerminal" }, () => { + const caps = detectCapabilities(); + assert.strictEqual(caps.images, "kitty"); + assert.strictEqual(caps.trueColor, true); + assert.strictEqual(caps.hyperlinks, true); + }); + }); + + it("enables images and hyperlinks for Warp via WARP_SESSION_ID", () => { + withEnv({ WARP_SESSION_ID: "some-session-id" }, () => { + const caps = detectCapabilities(); + assert.strictEqual(caps.images, "kitty"); + assert.strictEqual(caps.trueColor, true); + assert.strictEqual(caps.hyperlinks, true); + }); + }); + + it("enables images and hyperlinks for Warp via WARP_TERMINAL_SESSION_UUID", () => { + withEnv({ WARP_TERMINAL_SESSION_UUID: "d0e1a2e5-7ca7-44cd-9037-ac7222011161" }, () => { + const caps = detectCapabilities(); + assert.strictEqual(caps.images, "kitty"); + assert.strictEqual(caps.trueColor, true); + assert.strictEqual(caps.hyperlinks, true); + }); + }); + + it("disables images for Warp inside tmux", () => { + withEnv( + { + TERM_PROGRAM: "WarpTerminal", + TMUX: "/tmp/tmux-1000/default,1234,0", + TERM: "tmux-256color", + }, + () => { + const caps = detectCapabilities(() => true); + assert.strictEqual(caps.images, null); + assert.strictEqual(caps.hyperlinks, true); + }, + ); + }); + it("enables hyperlinks for iTerm2", () => { withEnv({ TERM_PROGRAM: "iterm.app" }, () => { const caps = detectCapabilities();