@@ -13,6 +13,7 @@ import (
1313
1414 tea "charm.land/bubbletea/v2"
1515 "github.com/charmbracelet/crush/internal/uiutil"
16+ uv "github.com/charmbracelet/ultraviolet"
1617 "github.com/charmbracelet/x/ansi"
1718 "github.com/charmbracelet/x/ansi/kitty"
1819 "github.com/charmbracelet/x/mosaic"
@@ -33,6 +34,8 @@ type Capabilities struct {
3334 // SupportsKittyGraphics indicates whether the terminal supports the Kitty
3435 // graphics protocol.
3536 SupportsKittyGraphics bool
37+ // Env is the terminal environment variables.
38+ Env uv.Environ
3639}
3740
3841// CellSize returns the size of a single terminal cell in pixels.
@@ -55,12 +58,15 @@ func CalculateCellSize(pixelWidth, pixelHeight, charWidth, charHeight int) CellS
5558
5659// RequestCapabilities is a [tea.Cmd] that requests the terminal to report
5760// its image related capabilities to the program.
58−func RequestCapabilities() tea.Cmd {
59− return tea.Raw(
60− ansi.WindowOp(14) + // Window size in pixels
61− // ID 31 is just a random ID used to detect Kitty graphics support.
62− ansi.KittyGraphics([]byte("AAAA"), "i=31", "s=1", "v=1", "a=q", "t=d", "f=24"),
63− )
61+func RequestCapabilities(env uv.Environ) tea.Cmd {
62+ winOpReq := ansi.WindowOp(14) // Window size in pixels
63+ // ID 31 is just a random ID used to detect Kitty graphics support.
64+ kittyReq := ansi.KittyGraphics([]byte("AAAA"), "i=31", "s=1", "v=1", "a=q", "t=d", "f=24")
65+ if _, isTmux := env.LookupEnv("TMUX"); isTmux {
66+ kittyReq = ansi.TmuxPassthrough(kittyReq)
67+ }
68+
69+ return tea.Raw(winOpReq + kittyReq)
6470}
6571
6672// TransmittedMsg is a message indicating that an image has been transmitted to
@@ -161,7 +167,7 @@ func HasTransmitted(id string, cols, rows int) bool {
161167
162168// Transmit transmits the image data to the terminal if needed. This is used to
163169// cache the image on the terminal for later rendering.
164−func (e Encoding) Transmit(id string, img image.Image, cs CellSize, cols, rows int) tea.Cmd {
170+func (e Encoding) Transmit(id string, img image.Image, cs CellSize, cols, rows int, tmux bool) tea.Cmd {
165171 if img == nil {
166172 return nil
167173 }
@@ -192,7 +198,6 @@ func (e Encoding) Transmit(id string, img image.Image, cs CellSize, cols, rows i
192198 bounds := img.Bounds()
193199 imgWidth := bounds.Dx()
194200 imgHeight := bounds.Dy()
195−
196201 imgID := int(key.Hash())
197202 if err := kitty.EncodeGraphics(&buf, img, &kitty.Options{
198203 ID: imgID,
@@ -205,9 +210,19 @@ func (e Encoding) Transmit(id string, img image.Image, cs CellSize, cols, rows i
205210 Rows: rows,
206211 VirtualPlacement: true,
207212 Quite: 1,
213+ Chunk: true,
214+ ChunkFormatter: func(chunk string) string {
215+ if tmux {
216+ return ansi.TmuxPassthrough(chunk)
217+ }
218+ return chunk
219+ },
208220 }); err != nil {
209221 slog.Error("failed to encode image for kitty graphics", "err", err)
210− return uiutil.ReportError(fmt.Errorf("failed to encode image"))
222+ return uiutil.InfoMsg{
223+ Type: uiutil.InfoTypeError,
224+ Msg: "failed to encode image",
225+ }
211226 }
212227
213228 return tea.RawMsg{Msg: buf.String()}