Kitty Graphics Protocol in OCaml
terminal
graphics
ocaml
1(*---------------------------------------------------------------------------
2 Copyright (c) 2025 Anil Madhavapeddy. All rights reserved.
3 SPDX-License-Identifier: ISC
4 ---------------------------------------------------------------------------*)
5
6(* Terminal Environment Detection *)
7
8type graphics_mode = [ `Auto | `Enabled | `Disabled | `Tmux ]
9
10let is_kitty () =
11 Option.is_some (Sys.getenv_opt "KITTY_WINDOW_ID") ||
12 (match Sys.getenv_opt "TERM" with
13 | Some term -> String.lowercase_ascii term = "xterm-kitty"
14 | None -> false) ||
15 (match Sys.getenv_opt "TERM_PROGRAM" with
16 | Some prog -> String.lowercase_ascii prog = "kitty"
17 | None -> false)
18
19let is_wezterm () =
20 Option.is_some (Sys.getenv_opt "WEZTERM_PANE") ||
21 (match Sys.getenv_opt "TERM_PROGRAM" with
22 | Some prog -> String.lowercase_ascii prog = "wezterm"
23 | None -> false)
24
25let is_ghostty () =
26 Option.is_some (Sys.getenv_opt "GHOSTTY_RESOURCES_DIR") ||
27 (match Sys.getenv_opt "TERM_PROGRAM" with
28 | Some prog -> String.lowercase_ascii prog = "ghostty"
29 | None -> false)
30
31let is_graphics_terminal () =
32 is_kitty () || is_wezterm () || is_ghostty ()
33
34let is_tmux () = Kgp_tmux.is_active ()
35
36let is_interactive () =
37 Unix.isatty Unix.stdout
38
39let is_pager () =
40 (* Not interactive = likely piped to pager *)
41 not (is_interactive ()) ||
42 (* PAGER set and not in a known graphics terminal *)
43 (Option.is_some (Sys.getenv_opt "PAGER") && not (is_graphics_terminal ()))
44
45let resolve_mode = function
46 | `Disabled -> `Placeholder
47 | `Enabled -> `Graphics
48 | `Tmux -> `Tmux
49 | `Auto ->
50 if is_pager () || not (is_interactive ()) then
51 `Placeholder
52 else if is_tmux () then
53 (* Inside tmux - use passthrough if underlying terminal supports graphics *)
54 if is_graphics_terminal () then `Tmux
55 else `Placeholder
56 else if is_graphics_terminal () then
57 `Graphics
58 else
59 `Placeholder
60
61let supports_graphics mode =
62 match resolve_mode mode with
63 | `Graphics | `Tmux -> true
64 | `Placeholder -> false