<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Tmux on Блог Сергея Клюкина</title><link>https://sklukin.ru/tags/tmux/</link><description>Recent content in Tmux on Блог Сергея Клюкина</description><generator>Hugo</generator><language>ru-RU</language><lastBuildDate>Thu, 30 Jul 2026 15:06:38 +0500</lastBuildDate><atom:link href="https://sklukin.ru/tags/tmux/index.xml" rel="self" type="application/rss+xml"/><item><title>Kitty вместо iTerm: конфиг целиком в git, startup sessions и грабли с tmux по ssh</title><link>https://sklukin.ru/posts/kitty-vs-iterm/</link><pubDate>Wed, 25 Feb 2026 16:30:00 +0500</pubDate><guid>https://sklukin.ru/posts/kitty-vs-iterm/</guid><description>Почему я ушёл с iTerm на Kitty: чем plist отличается от конфига, startup sessions под каждый проект, сплиты вместо tmux и один реальный косяк с terminfo по ssh.</description><content:encoded><![CDATA[<p>Я давно привык, что всё настраивается файлом: vim, tmux, zsh, docker-compose — конфиг лежит в git, правится руками, переносится на новую машину за минуту. iTerm на этом фоне всегда стоял особняком: кликаешь по меню, идёшь в Preferences, настраиваешь мышкой.</p>
<p>Ниже — почему я переехал на Kitty, что именно в конфиге и на какой ерунде я потерял вечер.</p>
<h2 id="почему-именно-iterm-перестал-устраивать">Почему именно iTerm перестал устраивать</h2>
<p>Сразу оговорюсь: iTerm не плохой. Он стабильный, у него отличный поиск по скроллбеку, и большинству людей его хватает с запасом.</p>
<p>Дальше идёт возражение, которое я слышу каждый раз: «настройки iTerm тоже можно держать в git, есть же экспорт в plist». Формально — да. Практически это выглядит так:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="nt">&lt;key&gt;</span>New Bookmarks<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;array&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;dict&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;key&gt;</span>ASCII Anti Aliased<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;key&gt;</span>Non Ascii Font<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>Monaco 12<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">        ...
</span></span></code></pre></div><p>Проблема не в том, что файла нет. Проблема в том, что этот файл:</p>
<ul>
<li><strong>не читается глазами</strong> — чтобы понять, что поменялось, нужен diff по XML-структуре, а не по смыслу;</li>
<li><strong>не комментируется</strong> — нельзя написать рядом «поставил 120%, иначе глаза устают»;</li>
<li><strong>не мержится</strong> — конфликт в plist на двух машинах разруливается вручную и болезненно;</li>
<li><strong>не правится руками</strong> — редактируешь всё равно через GUI, plist только выгружаешь.</li>
</ul>
<p>То есть это не конфиг, а дамп состояния. Разница примерно как между <code>docker-compose.yml</code> и снапшотом контейнера.</p>
<p>У Kitty конфиг — обычный текстовый файл с комментариями, который перезагружается без рестарта.</p>
<h2 id="вау-момент-startup-sessions">Вау-момент: startup sessions</h2>
<p>Момент, после которого я перестал сомневаться.</p>
<p>Kitty умеет описывать стартовое состояние окна отдельным файлом. Не скриптом, не набором alias — обычным конфигом:</p>
<pre tabindex="0"><code class="language-conf" data-lang="conf">os_window_state maximized

new_tab Back console
cd ~/Develop/some_app
launch zsh

new_tab Back Claude
cd ~/Develop/some_app
launch zsh -ic &#34;claude; exec zsh&#34;
</code></pre><p>Путь указывается в основном конфиге:</p>
<pre tabindex="0"><code class="language-conf" data-lang="conf">startup_session ~/.config/kitty/sessions/myapp.conf
</code></pre><p>Запускаю Kitty — окно разворачивается на весь экран (именно maximized, с доком и менюбаром, а не fullscreen), открываются две вкладки: сервис в нужной директории и рядом Claude для того же сервиса. Ноль ручных действий.</p>
<p>Под каждый проект — свой файл сессии. Всё в git.</p>
<h2 id="настройки-которые-стоит-объяснить">Настройки, которые стоит объяснить</h2>
<p>Полный конфиг я приложил в конце. Здесь — только то, что не очевидно из названия параметра.</p>
<h3 id="сплиты-вместо-tmux-для-локальной-работы">Сплиты вместо tmux для локальной работы</h3>
<pre tabindex="0"><code class="language-conf" data-lang="conf">enabled_layouts splits:split_axis=horizontal,fat,tall,stack

map f5 launch --location=hsplit --cwd=current
map f6 launch --location=vsplit --cwd=current
map ctrl+shift+z toggle_layout stack
</code></pre><p>Ключевое здесь — <code>--cwd=current</code>: новый сплит открывается в той же директории, а не в домашней. Именно это убрало у меня необходимость в tmux для локальных сессий — раньше tmux был нужен ровно за панели.</p>
<p><code>ctrl+shift+z</code> разворачивает текущий сплит на всё окно и возвращает обратно, аналог <code>tmux resize-pane -Z</code>. Остальные панели никуда не деваются.</p>
<h3 id="уведомление-о-долгой-команде">Уведомление о долгой команде</h3>
<pre tabindex="0"><code class="language-conf" data-lang="conf">notify_on_cmd_finish invisible 30
</code></pre><p>Самая недооценённая настройка. Если команда шла дольше 30 секунд и окно в этот момент неактивно — прилетит системное уведомление. Ушёл читать почту, пока идёт билд — тебя позовут.</p>
<p>Слово <code>invisible</code> важно: уведомление приходит только когда окно не на виду. Иначе бы дёргало на каждый <code>go build</code>.</p>
<h3 id="shell-integration-и-remote-control">Shell integration и remote control</h3>
<pre tabindex="0"><code class="language-conf" data-lang="conf">allow_remote_control yes
shell_integration    enabled
</code></pre><p><code>shell_integration</code> даёт то, чего в терминалах обычно нет: Kitty начинает понимать, где кончается вывод одной команды и начинается другая. Отсюда прыжки по промптам и подсветка границ вывода.</p>
<p><code>allow_remote_control</code> открывает управление из скриптов — <code>kitty @ launch</code>, <code>kitty @ set-tab-title</code> и прочее. Нужно, если собираешься автоматизировать раскладку окон. Если не собираешься — лучше не включать: это всё-таки открытый сокет управления терминалом.</p>
<h3 id="мелочи-которые-я-выбрал-под-себя">Мелочи, которые я выбрал под себя</h3>
<pre tabindex="0"><code class="language-conf" data-lang="conf">modify_font cell_height 120%
scrollback_lines 10000
copy_on_select yes
</code></pre><p><code>cell_height 120%</code> — больше воздуха между строками. Чисто вопрос глаз, кому-то покажется разреженно.</p>
<p><code>scrollback_lines 10000</code> — мне столько хватает, чтобы отлистать вывод неудачного деплоя целиком. Гоняешь очень болтливые логи — ставь больше, память там копеечная.</p>
<p><code>copy_on_select</code> — выделил, уже в буфере. Привычка из Linux, на macOS сначала непривычно.</p>
<p>Nerd Font (<code>JetBrainsMono Nerd Font Mono</code>) нужен не сам по себе, а если у тебя starship, neovim с иконками или powerline-таббар — без него вместо иконок будут квадраты.</p>
<h2 id="что-реально-поломалось-tmux-по-ssh">Что реально поломалось: tmux по ssh</h2>
<p>Единственная настоящая проблема за всё время.</p>
<p>При подключении по ssh на машину, где живёт tmux, ломались escape-последовательности: съезжали цвета, мусорились рамки, местами не работали клавиши. Причина в том, что Kitty представляется как <code>TERM=xterm-kitty</code>, а на удалённой машине такого terminfo нет — она просто не знает, что это за терминал.</p>
<p>Правильное решение оказалось встроенным: <code>kitty +kitten ssh</code> сам доставляет terminfo на удалённый хост перед подключением.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># ~/.zshrc</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span> <span class="s2">&#34;</span><span class="nv">$TERM</span><span class="s2">&#34;</span> <span class="o">=</span> <span class="s2">&#34;xterm-kitty&#34;</span> <span class="o">]</span> <span class="o">&amp;&amp;</span> <span class="nb">alias</span> <span class="nv">ssh</span><span class="o">=</span><span class="s2">&#34;kitty +kitten ssh&#34;</span>
</span></span></code></pre></div><p>Проверка <code>$TERM</code> тут не для красоты: без неё alias сломает ssh во всех остальных терминалах — в том же VS Code или в CI-шелле, где <code>kitty</code> в PATH может и не быть.</p>
<p>После этого проблема ушла полностью.</p>
<p>Альтернатива, если kitten ssh почему-то не подходит — прописать <code>TERM=xterm-256color</code> перед подключением. Работает, но теряются возможности, за которые Kitty и брали.</p>
<h2 id="полный-kittyconf">Полный <code>kitty.conf</code></h2>
<details>
<summary>Конфиг целиком, с комментариями</summary>
<pre tabindex="0"><code class="language-conf" data-lang="conf"># Kitty Configuration
# Путь: ~/.config/kitty/kitty.conf
# Перезагрузка без рестарта: Ctrl+Shift+F5 (Linux) / Ctrl+Cmd+, (macOS)

# ─────────────────────────────────────────────
# 1. ШРИФТЫ
# ─────────────────────────────────────────────
# Установи Nerd Font: https://www.nerdfonts.com/font-downloads
# brew install --cask font-jetbrains-mono-nerd-font  (macOS)

font_family      JetBrainsMono Nerd Font Mono
bold_font        auto
italic_font      auto
bold_italic_font auto
font_size        12.0

# Межстрочный интервал — чуть увеличен для читаемости
modify_font cell_height 120%

# Лигатуры (-&gt;  =&gt;  !=  ===  и т.д.)
disable_ligatures never

# ─────────────────────────────────────────────
# 2. ТЕМА
# ─────────────────────────────────────────────
# Выбрать тему интерактивно: kitty +kitten themes
# После выбора тема сохранится в current-theme.conf

# BEGIN_KITTY_THEME
# Catppuccin-Mocha
include current-theme.conf
# END_KITTY_THEME

# ─────────────────────────────────────────────
# 3. ПРОЗРАЧНОСТЬ И РАЗМЫТИЕ
# ─────────────────────────────────────────────

background_opacity 0.92
background_blur    25

# ─────────────────────────────────────────────
# 4. КУРСОР
# ─────────────────────────────────────────────

cursor_shape           beam
cursor_beam_thickness  2.0
cursor_blink_interval  0.5
cursor_stop_blinking_after 15.0

# Анимация следа курсора (kitty 0.38+)
# cursor_trail          3
# cursor_trail_decay    0.1 0.4
# cursor_trail_start_threshold 2

# ─────────────────────────────────────────────
# 5. SCROLLBACK
# ─────────────────────────────────────────────

scrollback_lines 10000

# ─────────────────────────────────────────────
# 6. ЗВУК И УВЕДОМЛЕНИЯ
# ─────────────────────────────────────────────

enable_audio_bell    no
visual_bell_duration 0.0
bell_on_tab          &#34;🔔 &#34;

# Уведомление при завершении долгой команды (30+ сек)
notify_on_cmd_finish invisible 30

# ─────────────────────────────────────────────
# 7. МЫШЬ И КОПИРОВАНИЕ
# ─────────────────────────────────────────────

copy_on_select         yes
strip_trailing_spaces  smart

# URL
url_style        curly
open_url_with    default
detect_urls      yes

# ─────────────────────────────────────────────
# 8. ОКНО
# ─────────────────────────────────────────────

# Убрать рамку окна (titlebar) — на macOS выглядит чисто
hide_window_decorations titlebar-only

# Отступы внутри окна
window_padding_width  8

# Рамки между сплитами
window_border_width   1pt
active_border_color   #89b4fa
inactive_border_color #313244

draw_minimal_borders  yes
confirm_os_window_close 0

# Начальный размер окна
remember_window_size  yes
initial_window_width  120c
initial_window_height 35c

# ─────────────────────────────────────────────
# 9. TAB BAR
# ─────────────────────────────────────────────

tab_bar_edge         bottom
tab_bar_style        powerline
tab_powerline_style  slanted
tab_bar_min_tabs     2

active_tab_foreground   #1e1e2e
active_tab_background   #89b4fa
active_tab_font_style   bold
inactive_tab_foreground #cdd6f4
inactive_tab_background #313244
inactive_tab_font_style normal

# ─────────────────────────────────────────────
# 10. LAYOUTS (сплиты)
# ─────────────────────────────────────────────

enabled_layouts splits:split_axis=horizontal,fat,tall,stack

# ─────────────────────────────────────────────
# 11. SHELL INTEGRATION &amp; REMOTE CONTROL
# ─────────────────────────────────────────────

allow_remote_control yes
shell_integration    enabled

# ─────────────────────────────────────────────
# 12. ГОРЯЧИЕ КЛАВИШИ
# ─────────────────────────────────────────────

# --- Сплиты ---
map f5                launch --location=hsplit --cwd=current
map f6                launch --location=vsplit --cwd=current

# Навигация между сплитами
map cmd+shift+h neighboring_window left
map cmd+shift+l neighboring_window right
map cmd+shift+k neighboring_window up
map cmd+shift+j neighboring_window down

# Ресайз сплитов
map ctrl+shift+alt+left  resize_window narrower  2
map ctrl+shift+alt+right resize_window wider     2
map ctrl+shift+alt+up    resize_window taller    2
map ctrl+shift+alt+down  resize_window shorter   2

# --- Табы ---
map ctrl+shift+t      new_tab_with_cwd
map ctrl+shift+w      close_tab
map ctrl+shift+right  next_tab
map ctrl+shift+left   previous_tab
map ctrl+shift+.      move_tab_forward
map ctrl+shift+,      move_tab_backward

map cmd+1 goto_tab 1
map cmd+2 goto_tab 2
map cmd+3 goto_tab 3
map cmd+4 goto_tab 4
map cmd+5 goto_tab 5
map cmd+6 goto_tab 6
map cmd+7 goto_tab 7
map cmd+8 goto_tab 8
map cmd+9 goto_tab 9

# --- Новое окно в текущей директории ---
map ctrl+shift+enter  new_window_with_cwd

# --- Полный экран для текущего сплита (toggle stack layout) ---
map ctrl+shift+z      toggle_layout stack

# --- Перезагрузка конфига ---
# Linux:  Ctrl+Shift+F5 (по умолчанию)
# macOS:  Ctrl+Cmd+, (по умолчанию)

# ─────────────────────────────────────────────
# 13. macOS-СПЕЦИФИЧНОЕ
# ─────────────────────────────────────────────

# Opt работает как Alt для терминальных приложений
macos_option_as_alt yes

# Не закрывать Kitty при закрытии последнего окна
macos_quit_when_last_window_closed no

# Paste по physical key position (не зависит от раскладки)
map cmd+0x76 paste_from_clipboard
</code></pre></details>
<h2 id="кому-это-не-нужно">Кому это не нужно</h2>
<p>Честно про границы, чтобы не тратить чужое время:</p>
<ul>
<li><strong>Если тебя устраивает iTerm</strong> — переезжать незачем. Выигрыш здесь не в скорости, а в воспроизводимости конфига. Не болит — не лечи.</li>
<li><strong>Если ты живёшь в tmux</strong> и он настроен под себя — сплиты Kitty тебе не нужны, а половина смысла переезда именно в них.</li>
<li><strong>Если работаешь в основном по ssh</strong> — большая часть настроек касается локального терминала, а на удалёнке ты всё равно в tmux на той стороне.</li>
</ul>
<p>Kitty стоит смотреть, если тебе близка мысль «конфигурация — это файл в репозитории», и раздражает, что терминал из этой картины выпадает.</p>
<h2 id="итог">Итог</h2>
<p>Обратно на iTerm не тянуло ни разу. Startup sessions закрыли последний аргумент — раскладка рабочего места стала таким же файлом в git, как <code>.zshrc</code> и <code>init.lua</code>.</p>
<p>Из неожиданного: сплиты Kitty вытеснили tmux из локальной работы полностью. Я этого не планировал, но панелями пользовался только за них.</p>
<p>Если пробовали WezTerm или Ghostty и остались там — расскажите, что оказалось решающим. Мне правда интересно, чего я не увидел.</p>
]]></content:encoded></item></channel></rss>