diff --git a/bold_is_bright.patch b/bold_is_bright.patch
new file mode 100644
index 0000000..4a95081
--- /dev/null
+++ b/bold_is_bright.patch
@@ -0,0 +1,849 @@
+diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
+index c64877153..ed2930008 100644
+--- a/.github/FUNDING.yml
++++ b/.github/FUNDING.yml
+@@ -1,4 +1,2 @@
+-github: kovidgoyal
+-patreon: kovidgoyal
+-liberapay: kovidgoyal
++custom: https://my.fsf.org/donate
+ custom: https://sw.kovidgoyal.net/kitty/support.html
+diff --git a/README.asciidoc b/README.asciidoc
+deleted file mode 100644
+index 5a24555ee..000000000
+--- a/README.asciidoc
++++ /dev/null
+@@ -1,14 +0,0 @@
+-= kitty - the fast, feature-rich, cross-platform, GPU based terminal
+-
+-See https://sw.kovidgoyal.net/kitty/[the kitty website].
+-
+-image:https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg["Build status", link="https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI"]
+-
+-https://sw.kovidgoyal.net/kitty/faq/[Frequently Asked Questions]
+-
+-To ask other questions about kitty usage, use either the https://github.com/kovidgoyal/kitty/discussions/[discussions on GitHub] or the
+-https://www.reddit.com/r/KittyTerminal[Reddit community]
+-
+-Packaging status in various repositories:
+-
+-image:https://repology.org/badge/vertical-allrepos/kitty.svg["Packaging status", link="https://repology.org/project/kitty/versions"]
+diff --git a/README.md b/README.md
+new file mode 100644
+index 000000000..d02f48469
+--- /dev/null
++++ b/README.md
+@@ -0,0 +1,49 @@
++
++
++
++KittyPatch
++
++
++forked from kitty
++
++
++
++
++
++A blazingly fast GPU based terminal emulator.
++
++
++
++(With added extras)
++
++
++
++---
++
++
++
++
++
++
++
++
++
++Sneak Peek ↓
++
++
++
++
++KittyPatch adds the bold_is_bright
config option, which kitty does not and will likely never support!
++
++
++---
++
++
++Instructions ↓
++
++
++
++
++For now, you'll need to build the latest master
branch from source.
++
++
+diff --git a/current-version.txt b/current-version.txt
+new file mode 100644
+index 000000000..918820be2
+--- /dev/null
++++ b/current-version.txt
+@@ -0,0 +1 @@
++0.19.3
+\ No newline at end of file
+diff --git a/docs/binary.rst b/docs/binary.rst
+index 4b60736fe..1d8c4a667 100644
+--- a/docs/binary.rst
++++ b/docs/binary.rst
+@@ -31,7 +31,7 @@ Manually installing
+
+ If something goes wrong or you simply do not want to run the installer, you can
+ manually download and install |kitty| from the `GitHub releases page
+-`__. If you are on macOS, download
++`__. If you are on macOS, download
+ the :file:`.dmg` and install as normal. If you are on Linux, download the
+ tarball and extract it into a directory. The |kitty| executable will be in the
+ :file:`bin` sub-directory.
+diff --git a/docs/build.rst b/docs/build.rst
+index 6f515ea81..fcf25a94e 100644
+--- a/docs/build.rst
++++ b/docs/build.rst
+@@ -1,9 +1,9 @@
+ Build from source
+ ==================
+
+-.. image:: https://github.com/kovidgoyal/kitty/workflows/CI/badge.svg
++.. image:: https://github.com/KittyPatch/kitty/workflows/CI/badge.svg
+ :alt: Build status
+- :target: https://github.com/kovidgoyal/kitty/actions?query=workflow%3ACI
++ :target: https://github.com/KittyPatch/kitty/actions?query=workflow%3ACI
+
+ .. highlight:: sh
+
+@@ -154,7 +154,7 @@ Notes for Linux/macOS packagers
+ ----------------------------------
+
+ The released |kitty| source code is available as a `tarball`_ from
+-`the GitHub releases page `__.
++`the GitHub releases page `__.
+
+ While |kitty| does use Python, it is not a traditional Python package, so please
+ do not install it in site-packages.
+diff --git a/docs/conf.py b/docs/conf.py
+index 721ce7d60..ac1a6c78e 100644
+--- a/docs/conf.py
++++ b/docs/conf.py
+@@ -33,8 +33,8 @@
+ # -- Project information -----------------------------------------------------
+
+ project = 'kitty'
+-copyright = time.strftime('%Y, Kovid Goyal')
+-author = 'Kovid Goyal'
++copyright = time.strftime('%Y, Kovid Goyal, KittyPatch')
++author = 'Kovid Goyal, KittyPatch'
+ building_man_pages = 'man' in sys.argv
+
+ # The short X.Y version
+@@ -100,7 +100,7 @@
+ rst_prolog = '''
+ .. |kitty| replace:: *kitty*
+ .. |version| replace:: VERSION
+-.. _tarball: https://github.com/kovidgoyal/kitty/releases/download/vVERSION/kitty-VERSION.tar.xz
++.. _tarball: https://github.com/KittyPatch/kitty/releases/download/vVERSION/kitty-VERSION.tar.xz
+ .. role:: italic
+
+ '''.replace('VERSION', str_version)
+@@ -215,7 +215,7 @@ def commit_role(
+ f'GitHub commit id "{text}" not recognized.', line=lineno)
+ prb = inliner.problematic(rawtext, rawtext, msg)
+ return [prb], [msg]
+- url = f'https://github.com/kovidgoyal/kitty/commit/{commit_id}'
++ url = f'https://github.com/KittyPatch/kitty/commit/{commit_id}'
+ set_classes(options)
+ short_id = subprocess.check_output(
+ f'git rev-list --max-count=1 --abbrev-commit --skip=# {commit_id}'.split()).decode('utf-8').strip()
+diff --git a/docs/support.rst b/docs/support.rst
+index 373714812..c0ff06981 100644
+--- a/docs/support.rst
++++ b/docs/support.rst
+@@ -1,5 +1,21 @@
++A message from us at KittyPatch
++===============================
++
++KittyPatch was created as a home for useful features that are unavailable
++in the kitty main branch. To this end, we do not accept donations directly.
++
++If you wish to support KittyPatch: share your ideas and spread the word.
++
++If you still wish to donate, please `support the Free Software Foundation
++`.
++
++
++
++A message from the maintainer of Kitty
++======================================
+ Support kitty development ❤️
+ ==============================
++>>>>>>> upstream/master
+
+ My goal with |kitty| is to move the stagnant terminal ecosystem forward. To that
+ end kitty has many foundational features, such as: :doc:`image support
+diff --git a/kitty/cell_vertex.glsl b/kitty/cell_vertex.glsl
+index 0eda08295..aa84d4d7a 100644
+--- a/kitty/cell_vertex.glsl
++++ b/kitty/cell_vertex.glsl
+@@ -3,6 +3,7 @@
+
+ #define {WHICH_PROGRAM}
+ #define NOT_TRANSPARENT
++#define BOLD_SHIFT {BOLD_SHIFT}
+ #define DECORATION_SHIFT {DECORATION_SHIFT}
+ #define REVERSE_SHIFT {REVERSE_SHIFT}
+ #define STRIKE_SHIFT {STRIKE_SHIFT}
+@@ -17,6 +18,7 @@ layout(std140) uniform CellRenderData {
+ float xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, use_cell_bg_for_selection_fg, use_cell_fg_for_selection_fg, use_cell_for_selection_bg;
+
+ uint default_fg, default_bg, highlight_fg, highlight_bg, cursor_fg, cursor_bg, url_color, url_style, inverted;
++ uint bold_is_bright;
+
+ uint xnum, ynum, cursor_fg_sprite_idx;
+ float cursor_x, cursor_y, cursor_w;
+@@ -93,6 +95,22 @@ vec3 color_to_vec(uint c) {
+ return vec3(gamma_lut[r], gamma_lut[g], gamma_lut[b]);
+ }
+
++uint byte_to_bool(uint n) {
++ uint n1 = (n >> 1) | n;
++ uint n2 = (n1 >> 2) | n1;
++ uint n3 = (n2 >> 4) | n2;
++ return n3 & 1u;
++}
++
++uint brighten_color(uint c, uint is_bold) {
++ uint table_idx = (c >> 8) & 0xFFu;
++ uint is_table_color = c & 1u;
++ uint is_rgb_color = byte_to_bool(c & 0xFEu);
++ uint is_8bit_color = byte_to_bool(table_idx & 0xF8u);
++ uint should_brighten = bold_is_bright * is_bold * (1u >> (is_rgb_color + is_8bit_color)) * is_table_color;
++ return c | (0x800u * should_brighten);
++}
++
+ uint resolve_color(uint c, uint defval) {
+ // Convert a cell color to an actual color based on the color table
+ int t = int(c & BYTE_MASK);
+@@ -161,6 +179,7 @@ void main() {
+ // set cell color indices {{{
+ uvec2 default_colors = uvec2(default_fg, default_bg);
+ uint text_attrs = sprite_coords[3];
++ uint is_bold = ((text_attrs >> BOLD_SHIFT) & ONE);
+ uint is_reversed = ((text_attrs >> REVERSE_SHIFT) & ONE);
+ uint is_inverted = is_reversed + inverted;
+ int fg_index = fg_index_map[is_inverted];
+@@ -170,10 +189,10 @@ void main() {
+ float cell_has_block_cursor = cell_has_cursor * is_block_cursor;
+ int mark = int(text_attrs >> MARK_SHIFT) & MARK_MASK;
+ uint has_mark = uint(step(1, float(mark)));
+- uint bg_as_uint = resolve_color(colors[bg_index], default_colors[bg_index]);
++ uint bg_as_uint = resolve_color(brighten_color(colors[bg_index], is_bold), default_colors[bg_index]);
+ bg_as_uint = has_mark * color_table[NUM_COLORS + mark] + (ONE - has_mark) * bg_as_uint;
+ vec3 bg = color_to_vec(bg_as_uint);
+- uint fg_as_uint = resolve_color(colors[fg_index], default_colors[fg_index]);
++ uint fg_as_uint = resolve_color(brighten_color(colors[fg_index], is_bold), default_colors[fg_index]);
+ // }}}
+
+ // Foreground {{{
+diff --git a/kitty/fast_data_types.pyi b/kitty/fast_data_types.pyi
+index 5d0b39bea..c4253a4b6 100644
+--- a/kitty/fast_data_types.pyi
++++ b/kitty/fast_data_types.pyi
+@@ -265,6 +265,7 @@ CELL_FG_PROGRAM: int
+ CELL_PROGRAM: int
+ CELL_SPECIAL_PROGRAM: int
+ CSI: int
++BOLD: int
+ DCS: int
+ DECORATION: int
+ DIM: int
+diff --git a/kitty/options/definition.py b/kitty/options/definition.py
+index 4a80eadb4..17e003dc2 100644
+--- a/kitty/options/definition.py
++++ b/kitty/options/definition.py
+@@ -1328,6 +1328,10 @@
+ )
+ egr() # }}}
+
++opt('bold_is_bright', 'no',
++ option_type='to_bool', ctype='bool',
++ long_text='Display bold text with bright colors'
++ )
+
+ # colors {{{
+ agr('colors', 'Color scheme')
+diff --git a/kitty/options/parse.py b/kitty/options/parse.py
+index d4a607f15..1ce4bfe5a 100644
+--- a/kitty/options/parse.py
++++ b/kitty/options/parse.py
+@@ -100,6 +100,9 @@ def bell_path(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
+ def bold_font(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
+ ans['bold_font'] = str(val)
+
++ def bold_is_bright(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
++ ans['bold_is_bright'] = to_bool(val)
++
+ def bold_italic_font(self, val: str, ans: typing.Dict[str, typing.Any]) -> None:
+ ans['bold_italic_font'] = str(val)
+
+diff --git a/kitty/options/to-c-generated.h b/kitty/options/to-c-generated.h
+index c1ea350a2..249ea38e9 100644
+--- a/kitty/options/to-c-generated.h
++++ b/kitty/options/to-c-generated.h
+@@ -837,6 +837,19 @@ convert_from_opts_dim_opacity(PyObject *py_opts, Options *opts) {
+ Py_DECREF(ret);
+ }
+
++static void
++convert_from_python_bold_is_bright(PyObject *val, Options *opts) {
++ opts->bold_is_bright = PyObject_IsTrue(val);
++}
++
++static void
++convert_from_opts_bold_is_bright(PyObject *py_opts, Options *opts) {
++ PyObject *ret = PyObject_GetAttrString(py_opts, "bold_is_bright");
++ if (ret == NULL) return;
++ convert_from_python_bold_is_bright(ret, opts);
++ Py_DECREF(ret);
++}
++
+ static void
+ convert_from_python_mark1_foreground(PyObject *val, Options *opts) {
+ opts->mark1_foreground = color_as_int(val);
+@@ -1188,6 +1201,8 @@ convert_opts_from_python_opts(PyObject *py_opts, Options *opts) {
+ if (PyErr_Occurred()) return false;
+ convert_from_opts_dim_opacity(py_opts, opts);
+ if (PyErr_Occurred()) return false;
++ convert_from_opts_bold_is_bright(py_opts, opts);
++ if (PyErr_Occurred()) return false;
+ convert_from_opts_mark1_foreground(py_opts, opts);
+ if (PyErr_Occurred()) return false;
+ convert_from_opts_mark1_background(py_opts, opts);
+diff --git a/kitty/options/types.py b/kitty/options/types.py
+index dde02d82f..3ab3b0c65 100644
+--- a/kitty/options/types.py
++++ b/kitty/options/types.py
+@@ -71,6 +71,7 @@
+ 'bell_on_tab',
+ 'bell_path',
+ 'bold_font',
++ 'bold_is_bright',
+ 'bold_italic_font',
+ 'box_drawing_scale',
+ 'clear_all_mouse_actions',
+@@ -490,6 +491,7 @@ class Options:
+ bell_on_tab: str = '🔔 '
+ bell_path: typing.Optional[str] = None
+ bold_font: str = 'auto'
++ bold_is_bright: bool = False
+ bold_italic_font: str = 'auto'
+ box_drawing_scale: typing.Tuple[float, float, float, float] = (0.001, 1.0, 1.5, 2.0)
+ clear_all_mouse_actions: bool = False
+diff --git a/kitty/shaders.c b/kitty/shaders.c
+index b5e86f479..cd0062975 100644
+--- a/kitty/shaders.c
++++ b/kitty/shaders.c
+@@ -303,6 +303,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
+ GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity, use_cell_bg_for_selection_fg, use_cell_fg_for_selection_color, use_cell_for_selection_bg;
+
+ GLuint default_fg, default_bg, highlight_fg, highlight_bg, cursor_fg, cursor_bg, url_color, url_style, inverted;
++ GLuint bold_is_bright;
+
+ GLuint xnum, ynum, cursor_fg_sprite_idx;
+ GLfloat cursor_x, cursor_y, cursor_w;
+@@ -374,6 +375,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, c
+ rd->sprite_dx = 1.0f / (float)x; rd->sprite_dy = 1.0f / (float)y;
+ rd->inverted = inverted ? 1 : 0;
+ rd->background_opacity = os_window->is_semi_transparent ? os_window->background_opacity : 1.0f;
++ rd->bold_is_bright = OPT(bold_is_bright) ? 1 : 0;
+
+ #undef COLOR
+ rd->url_color = OPT(url_color); rd->url_style = OPT(url_style);
+diff --git a/kitty/state.c b/kitty/state.c
+index d06767266..f08b8bd3e 100644
+--- a/kitty/state.c
++++ b/kitty/state.c
+@@ -1130,6 +1130,7 @@ PYWRAP1(patch_global_colors) {
+ P(background); P(url_color);
+ P(mark1_background); P(mark1_foreground); P(mark2_background); P(mark2_foreground);
+ P(mark3_background); P(mark3_foreground);
++ P(bold_is_bright);
+ }
+ if (PyErr_Occurred()) return NULL;
+ Py_RETURN_NONE;
+diff --git a/kitty/state.h b/kitty/state.h
+index 454aa90d0..7353f5197 100644
+--- a/kitty/state.h
++++ b/kitty/state.h
+@@ -39,6 +39,7 @@ typedef struct {
+ char_type *select_by_word_characters_forward;
+ color_type url_color, background, foreground, active_border_color, inactive_border_color, bell_border_color, tab_bar_background, tab_bar_margin_color;
+ color_type mark1_foreground, mark1_background, mark2_foreground, mark2_background, mark3_foreground, mark3_background;
++ bool bold_is_bright;
+ monotonic_t repaint_delay, input_delay;
+ bool focus_follows_mouse;
+ unsigned int hide_window_decorations;
+diff --git a/kitty/window.py b/kitty/window.py
+index 959931877..b2017423a 100644
+--- a/kitty/window.py
++++ b/kitty/window.py
+@@ -44,6 +44,7 @@
+ from .fast_data_types import (
+ BGIMAGE_PROGRAM,
+ BLIT_PROGRAM,
++ BOLD,
+ CELL_BG_PROGRAM,
+ CELL_FG_PROGRAM,
+ CELL_PROGRAM,
+@@ -392,6 +393,7 @@ def __call__(self, semi_transparent: bool = False) -> None:
+ STRIKE_SHIFT=STRIKETHROUGH,
+ DIM_SHIFT=DIM,
+ DECORATION_SHIFT=DECORATION,
++ BOLD_SHIFT=BOLD,
+ MARK_SHIFT=MARK,
+ MARK_MASK=MARK_MASK,
+ DECORATION_MASK=DECORATION_MASK,
+diff --git a/logo/kitty-framed.svg b/logo/kitty-framed.svg
+index 310ea8a29..461f08320 100644
+--- a/logo/kitty-framed.svg
++++ b/logo/kitty-framed.svg
+@@ -1 +1,195 @@
+-
+\ No newline at end of file
++
++
+diff --git a/logo/kitty.svg b/logo/kitty.svg
+index dc4b6e42c..32d06f031 100644
+--- a/logo/kitty.svg
++++ b/logo/kitty.svg
+@@ -1 +1,206 @@
+-
+\ No newline at end of file
++
++
++
++
+diff --git a/publish.py b/publish.py
+index 20e082760..f555246be 100755
+--- a/publish.py
++++ b/publish.py
+@@ -25,7 +25,7 @@
+
+ os.chdir(os.path.dirname(os.path.abspath(__file__)))
+ docs_dir = os.path.abspath('docs')
+-publish_dir = os.path.abspath(os.path.join('..', 'kovidgoyal.github.io', 'kitty'))
++publish_dir = os.path.abspath(os.path.join('..', 'kittypatch.github.io', 'kitty'))
+ building_nightly = False
+ with open('kitty/constants.py') as f:
+ raw = f.read()
+@@ -101,7 +101,7 @@ def run_man(args: Any) -> None:
+
+
+ def run_html(args: Any) -> None:
+- call('make FAIL_WARN=1 "OPTS=-D analytics_id=G-XTJK3R7GF2" dirhtml', cwd=docs_dir)
++ call('make FAIL_WARN=1 "OPTS=-D analytics_id=UA-XXXXXXXX-X" dirhtml', cwd=docs_dir)
+ add_old_redirects('docs/_build/dirhtml')
+
+
diff --git a/disable-test_ssh_bootstrap_with_different_launchers.patch b/disable-test_ssh_bootstrap_with_different_launchers.patch
new file mode 100644
index 0000000..584815b
--- /dev/null
+++ b/disable-test_ssh_bootstrap_with_different_launchers.patch
@@ -0,0 +1,13 @@
+diff --git a/kitty_tests/ssh.py b/kitty_tests/ssh.py
+index 1f424146..d3cc191b 100644
+--- a/kitty_tests/ssh.py
++++ b/kitty_tests/ssh.py
+@@ -166,7 +166,7 @@ def test_ssh_bootstrap_with_different_launchers(self):
+ for sh in self.all_possible_sh:
+ if sh == 'sh' or 'python' in sh:
+ q = shutil.which(launcher)
+- if q:
++ if q and not 'zsh' in q:
+ with self.subTest(sh=sh, launcher=q), tempfile.TemporaryDirectory() as tdir:
+ self.check_bootstrap(sh, tdir, test_script='env; exit 0', SHELL_INTEGRATION_VALUE='', launcher=q)
+
diff --git a/fix-test_ssh_env_vars.patch b/fix-test_ssh_env_vars.patch
new file mode 100644
index 0000000..719b38b
--- /dev/null
+++ b/fix-test_ssh_env_vars.patch
@@ -0,0 +1,13 @@
+diff --git a/kitty_tests/ssh.py b/kitty_tests/ssh.py
+index 7b3bdbeb..710aeceb 100644
+--- a/kitty_tests/ssh.py
++++ b/kitty_tests/ssh.py
+@@ -272,8 +272,6 @@ def check_bootstrap(self, sh, home_dir, login_shell='', SHELL_INTEGRATION_VALUE=
+
+ def check_untar_or_fail():
+ q = pty.screen_contents()
+- if 'bzip2' in q:
+- raise ValueError('Untarring failed with screen contents:\n' + q)
+ return 'UNTAR_DONE' in q
+ pty.wait_till(check_untar_or_fail)
+ self.assertTrue(os.path.exists(os.path.join(home_dir, '.terminfo/kitty.terminfo')))
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..290ba63
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,27 @@
+{
+ "nodes": {
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1688438960,
+ "narHash": "sha256-aIFcxU2qtI/LupfwcwTbVbadrF1KZLw2tsxyyl7WYtU=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "62fed675bc20ceac4471d844164ec146888f0c27",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-23.05-small",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "nixpkgs": "nixpkgs"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..fce024a
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,54 @@
+# vim: set noet sw=2 ts=2 sts=2:
+{
+ description = "kitty";
+ inputs = {
+ nixpkgs.url = github:NixOS/nixpkgs/nixos-23.05-small;
+ };
+ outputs = { self, nixpkgs }:
+ let
+ allSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ];
+ forAllSystems = f: (nixpkgs.lib.genAttrs allSystems (system: f {
+ pkgs = import nixpkgs { inherit system; };
+ }));
+ in rec {
+ defaultPackage = forAllSystems ({pkgs}:
+ with pkgs;
+ callPackage ./kitty.nix { }
+ );
+ packages = forAllSystems ({pkgs}:
+ with pkgs;
+ { default = callPackage ./kitty.nix { }; }
+ );
+ devShell = forAllSystems ({pkgs}:
+ with pkgs;
+ let
+ sw = callPackage ./kitty.nix { };
+ environment =
+ (lib.attrsets.filterAttrs (n: v: null != (builtins.match "^[A-Z_]+$" n)) sw)
+ // { RAILS_ENV = "development"; };
+ q = lib.strings.escapeShellArg;
+ in
+ mkShell {
+ name = "kitty-dev";
+ inputsFrom = [sw];
+ shellHook = ''
+ ${lib.strings.concatStringsSep " " (builtins.attrValues (builtins.mapAttrs (n: v: "${n}=${q v}") environment))}
+ export ${lib.strings.concatStringsSep " " (builtins.attrValues (builtins.mapAttrs (n: v: q n) environment))}
+ '';
+ }
+ // environment
+ );
+
+ apps = forAllSystems ({pkgs}:
+ with pkgs;
+ let
+ kitty = callPackage ./kitty.nix { };
+ in {
+ server = {
+ type = "app";
+ program = "dev.sh";
+ };
+ }
+ );
+ };
+}
diff --git a/kitty.nix b/kitty.nix
new file mode 100644
index 0000000..36a6a6a
--- /dev/null
+++ b/kitty.nix
@@ -0,0 +1,244 @@
+{ lib, stdenv, fetchFromGitHub, python3Packages, libunistring
+, harfbuzz, fontconfig, pkg-config, ncurses, imagemagick
+, libstartup_notification, libGL, libX11, libXrandr, libXinerama, libXcursor
+, libxkbcommon, libXi, libXext, wayland-protocols, wayland
+, lcms2
+, librsync
+, openssl
+, installShellFiles
+, dbus
+, Libsystem ? null
+, Cocoa ? null
+, Kernel ? null
+, UniformTypeIdentifiers ? null
+, UserNotifications ? null
+, libcanberra
+, libicns
+, libpng
+, python3
+, zlib
+, bashInteractive
+, zsh
+, fish
+, nixosTests
+, go
+, buildGoModule
+, nix-update-script
+}:
+
+with python3Packages;
+buildPythonApplication rec {
+ pname = "kitty-patch";
+ version = "0.28.1";
+ format = "other";
+
+ src = fetchFromGitHub {
+ owner = "kovidgoyal";
+ repo = "kitty";
+ rev = "refs/tags/v${version}";
+ hash = "sha256-pAo+bT10rdQOf9j3imKWCCMFGm8KntUeTQUrEE1wYZc=";
+ };
+ vendorHash = "sha256-vq19exqsEtXhN20mgC5GCpYGm8s9AC6nlfCfG1lUiI8=";
+
+ buildInputs = [
+ harfbuzz
+ ncurses
+ lcms2
+ librsync
+ openssl.dev
+ ] ++ lib.optionals stdenv.isDarwin [
+ Cocoa
+ Kernel
+ UniformTypeIdentifiers
+ UserNotifications
+ libpng
+ python3
+ zlib
+ ] ++ lib.optionals (stdenv.isDarwin && stdenv.isx86_64) [
+ Libsystem
+ ] ++ lib.optionals stdenv.isLinux [
+ fontconfig libunistring libcanberra libX11
+ libXrandr libXinerama libXcursor libxkbcommon libXi libXext
+ wayland-protocols wayland dbus libGL
+ ];
+
+ nativeBuildInputs = [
+ installShellFiles
+ ncurses
+ pkg-config
+ sphinx
+ furo
+ sphinx-copybutton
+ sphinxext-opengraph
+ sphinx-inline-tabs
+ go
+ ] ++ lib.optionals stdenv.isDarwin [
+ imagemagick
+ libicns # For the png2icns tool.
+ ];
+
+ outputs = [ "out" "terminfo" "shell_integration" "kitten" ];
+
+ patches = [
+ # Gets `test_ssh_env_vars` to pass when `bzip2` is in the output of `env`.
+ ./fix-test_ssh_env_vars.patch
+
+ # Needed on darwin
+
+ # Gets `test_ssh_shell_integration` to pass for `zsh` when `compinit` complains about
+ # permissions.
+ ./zsh-compinit.patch
+
+ # Skip `test_ssh_bootstrap_with_different_launchers` when launcher is `zsh` since it causes:
+ # OSError: master_fd is in error condition
+ ./disable-test_ssh_bootstrap_with_different_launchers.patch
+
+ ./bold_is_bright.patch
+ ];
+
+ # Causes build failure due to warning
+ hardeningDisable = lib.optional stdenv.cc.isClang "strictoverflow";
+
+ CGO_ENABLED = 0;
+ GOFLAGS = "-trimpath";
+
+ go-modules = (buildGoModule {
+ pname = "kitty-go-modules";
+ inherit src vendorHash version;
+ }).go-modules;
+
+ configurePhase = ''
+ export GOCACHE=$TMPDIR/go-cache
+ export GOPATH="$TMPDIR/go"
+ export GOPROXY=off
+ cp -r --reflink=auto ${go-modules} vendor
+ '';
+
+ buildPhase = let
+ commonOptions = ''
+ --update-check-interval=0 \
+ --shell-integration=enabled\ no-rc
+ '';
+ darwinOptions = ''
+ --disable-link-time-optimization \
+ ${commonOptions}
+ '';
+ in ''
+ runHook preBuild
+ ${ lib.optionalString (stdenv.isDarwin && stdenv.isx86_64) "export MACOSX_DEPLOYMENT_TARGET=11" }
+ ${if stdenv.isDarwin then ''
+ ${python.pythonForBuild.interpreter} setup.py build ${darwinOptions}
+ make docs
+ ${python.pythonForBuild.interpreter} setup.py kitty.app ${darwinOptions}
+ '' else ''
+ ${python.pythonForBuild.interpreter} setup.py linux-package \
+ --egl-library='${lib.getLib libGL}/lib/libEGL.so.1' \
+ --startup-notification-library='${libstartup_notification}/lib/libstartup-notification-1.so' \
+ --canberra-library='${libcanberra}/lib/libcanberra.so' \
+ --fontconfig-library='${fontconfig.lib}/lib/libfontconfig.so' \
+ ${commonOptions}
+ ${python.pythonForBuild.interpreter} setup.py build-launcher
+ ''}
+ runHook postBuild
+ '';
+
+ nativeCheckInputs = [
+ pillow
+
+ # Shells needed for shell integration tests
+ bashInteractive
+ zsh
+ fish
+ ];
+
+ # skip failing tests due to darwin sandbox
+ preCheck = lib.optionalString stdenv.isDarwin ''
+ substituteInPlace kitty_tests/file_transmission.py \
+ --replace test_file_get dont_test_file_get \
+ --replace test_path_mapping_receive dont_test_path_mapping_receive
+ substituteInPlace kitty_tests/shell_integration.py \
+ --replace test_fish_integration dont_test_fish_integration
+ substituteInPlace kitty_tests/open_actions.py \
+ --replace test_parsing_of_open_actions dont_test_parsing_of_open_actions
+ substituteInPlace kitty_tests/ssh.py \
+ --replace test_ssh_connection_data dont_test_ssh_connection_data
+ substituteInPlace kitty_tests/fonts.py \
+ --replace 'class Rendering(BaseTest)' 'class Rendering'
+ # theme collection test starts an http server
+ rm tools/themes/collection_test.go
+ '';
+
+ checkPhase = ''
+ runHook preCheck
+
+ # Fontconfig error: Cannot load default config file: No such file: (null)
+ export FONTCONFIG_FILE=${fontconfig.out}/etc/fonts/fonts.conf
+
+ # Required for `test_ssh_shell_integration` to pass.
+ export TERM=kitty
+
+ make test
+ runHook postCheck
+ '';
+
+ installPhase = ''
+ runHook preInstall
+ mkdir -p $out
+ mkdir -p $kitten/bin
+ ${if stdenv.isDarwin then ''
+ mkdir "$out/bin"
+ ln -s ../Applications/kitty.app/Contents/MacOS/kitty "$out/bin/kitty"
+ ln -s ../Applications/kitty.app/Contents/MacOS/kitten "$out/bin/kitten"
+ cp ./kitty.app/Contents/MacOS/kitten "$kitten/bin/kitten"
+ mkdir "$out/Applications"
+ cp -r kitty.app "$out/Applications/kitty.app"
+
+ installManPage 'docs/_build/man/kitty.1'
+ '' else ''
+ cp -r linux-package/{bin,share,lib} $out
+ cp linux-package/bin/kitten $kitten/bin/kitten
+ ''}
+ wrapProgram "$out/bin/kitty" --prefix PATH : "$out/bin:${lib.makeBinPath [ imagemagick ncurses.dev ]}"
+
+ installShellCompletion --cmd kitty \
+ --bash <("$out/bin/kitty" +complete setup bash) \
+ --fish <("$out/bin/kitty" +complete setup fish2) \
+ --zsh <("$out/bin/kitty" +complete setup zsh)
+
+ terminfo_src=${if stdenv.isDarwin then
+ ''"$out/Applications/kitty.app/Contents/Resources/terminfo"''
+ else
+ "$out/share/terminfo"}
+
+ mkdir -p $terminfo/share
+ mv "$terminfo_src" $terminfo/share/terminfo
+
+ mkdir -p $out/nix-support
+ echo "$terminfo" >> $out/nix-support/propagated-user-env-packages
+
+ cp -r 'shell-integration' "$shell_integration"
+
+ runHook postInstall
+ '';
+
+ passthru = {
+ updateScript = nix-update-script {};
+ tests.test = nixosTests.terminal-emulators.kitty;
+ };
+
+ meta = with lib; {
+ homepage = "https://github.com/kovidgoyal/kitty";
+ description = "A modern, hackable, featureful, OpenGL based terminal emulator";
+ license = licenses.gpl3Only;
+ changelog = "https://sw.kovidgoyal.net/kitty/changelog/";
+ platforms = platforms.darwin ++ platforms.linux;
+ maintainers = with maintainers; [ tex rvolosatovs Luflosi adamcstephens ];
+ };
+} //
+ (if stdenv.isDarwin then
+ { KITTY_NO_LTO = ""; }
+ else {
+ KITTY_EGL_LIBRARY = "${lib.getLib libGL}/lib/libEGL.so.1";
+ KITTY_STARTUP_NOTIFICATION_LIBRARY = "${libstartup_notification}/lib/libstartup-notification-1.so";
+ KITTY_CANBERRA_LIBRARY = "${libcanberra}/lib/libcanberra.so";
+ })
diff --git a/zsh-compinit.patch b/zsh-compinit.patch
new file mode 100644
index 0000000..168f80c
--- /dev/null
+++ b/zsh-compinit.patch
@@ -0,0 +1,13 @@
+diff --git a/kitty_tests/ssh.py b/kitty_tests/ssh.py
+index 1f424146..d9a65d25 100644
+--- a/kitty_tests/ssh.py
++++ b/kitty_tests/ssh.py
+@@ -268,6 +268,8 @@ def check_untar_or_fail():
+ return 'UNTAR_DONE' in q
+ pty.wait_till(check_untar_or_fail)
+ self.assertTrue(os.path.exists(os.path.join(home_dir, '.terminfo/kitty.terminfo')))
++ if login_shell == 'zsh':
++ pty.send_cmd_to_child('y')
+ if SHELL_INTEGRATION_VALUE != 'enabled':
+ pty.wait_till(lambda: len(pty.screen_contents().splitlines()) > 1)
+ self.assertEqual(pty.screen.cursor.shape, 0)