Skip to content

Instantly share code, notes, and snippets.

@oleg-koval
Last active March 17, 2026 16:55
Show Gist options
  • Select an option

  • Save oleg-koval/77ff6d4332ee3c382ab24003f519afca to your computer and use it in GitHub Desktop.

Select an option

Save oleg-koval/77ff6d4332ee3c382ab24003f519afca to your computer and use it in GitHub Desktop.
Kitty terminal config — migrated from iTerm2 by Claude Code
import os
import subprocess
import sys
import tty
import termios
def main(args):
# Input prompt
sys.stdout.write('\033[1;34m╭─ Kitty AI Shell\033[0m\n')
sys.stdout.write('\033[1;34m╰─\033[0m Describe the command you need: ')
sys.stdout.flush()
description = sys.stdin.readline().strip()
if not description:
return None
sys.stdout.write('\033[2mThinking...\033[0m\n')
sys.stdout.flush()
# Call claude
try:
result = subprocess.run(
[
'/Users/olegkoval/.local/bin/claude', '-p',
'Output only a raw shell command with no explanation, '
'no markdown, no backticks: ' + description,
],
capture_output=True,
text=True,
timeout=30,
)
raw = result.stdout.strip()
except FileNotFoundError:
sys.stdout.write('\033[31mError: claude CLI not found in PATH\033[0m\n')
sys.stdout.flush()
input('Press Enter to close...')
return None
except subprocess.TimeoutExpired:
sys.stdout.write('\033[31mError: timed out waiting for claude\033[0m\n')
sys.stdout.flush()
input('Press Enter to close...')
return None
# Strip code fences and backticks
lines = raw.splitlines()
clean = [
l.strip().strip('`')
for l in lines
if l.strip() and not l.strip().startswith('```')
]
command = clean[0] if clean else ''
if not command:
sys.stdout.write('\033[31mNo command returned.\033[0m\n')
sys.stdout.flush()
input('Press Enter to close...')
return None
# Confirmation
sys.stdout.write(f'\n\033[1mRun this?\033[0m\n')
sys.stdout.write(f' \033[1;32m{command}\033[0m\n\n')
sys.stdout.write('[Enter] paste [Esc/q] cancel: ')
sys.stdout.flush()
fd = sys.stdin.fileno()
old = termios.tcgetattr(fd)
try:
tty.setraw(fd)
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
sys.stdout.write('\n')
sys.stdout.flush()
if ch in ('\r', '\n'):
return command
return None
def handle_result(args, answer, target_window_id, boss):
# Uses boss API (more reliable than kitten @ subprocess inside handle_result).
# If boss.window_id_map is unavailable in this Kitty version, fall back to:
# subprocess.run(['kitten', '@', '--to', 'unix:/tmp/kitty-socket',
# 'send-text', '--match', f'id:{target_window_id}', answer])
if answer:
w = boss.window_id_map.get(target_window_id)
if w:
w.paste_text(answer)
# Kitty Configuration — matching iTerm2 setup
# =============================================
# ===== Font =====
font_family Monaco
font_size 12.0
bold_font auto
italic_font auto
bold_italic_font auto
# ===== Window / Layout =====
remember_window_size no
initial_window_width 80c
initial_window_height 25c
# Layouts: enable splits (like iTerm2 panes)
# tall = vertical splits, fat = horizontal, splits = arbitrary, stack = fullscreen toggle
enabled_layouts splits,tall,fat,stack
# Window padding (pixels)
window_padding_width 4
# Draw a thin border between splits (like iTerm2 pane dividers)
window_border_width 1pt
# active_border_color #4488ff
# inactive_border_color #cccccc
# Dim inactive panes (iTerm2 has SplitPaneDimmingAmount)
inactive_text_alpha 0.7
# ===== Tabs =====
tab_bar_style powerline
tab_bar_edge bottom
tab_powerline_style slanted
tab_title_template "{index}: {title}"
active_tab_font_style bold
inactive_tab_font_style normal
# ===== Scrollback =====
scrollback_lines 1000
# Scrollback pager (like iTerm2's "show scrollback in new window")
scrollback_pager less --chop-long-lines --RAW-CONTROL-CHARS +INPUT_LINE_NUMBER
# ===== Shell =====
shell /bin/zsh
# ===== Transparency =====
background_opacity 1.0
# ===== Cursor =====
cursor_shape block
cursor_blink_interval 0
# ===== Bell (matching iTerm2: visual bell on, audio off) =====
enable_audio_bell no
visual_bell_duration 0.15
# visual_bell_color #444444
window_alert_on_bell yes
bell_on_tab "🔔 "
# ===== Mouse =====
mouse_hide_wait 3.0
copy_on_select clipboard
strip_trailing_spaces smart
# URL handling (like iTerm2 Semantic History — cmd+click opens URLs)
url_style curly
open_url_with default
detect_urls yes
url_prefixes file ftp ftps gemini git gopher http https irc ircs kitty mailto news sftp ssh
# ===== macOS Specific =====
macos_option_as_alt no
# macos_titlebar_color background
macos_quit_when_last_window_closed yes
macos_traditional_fullscreen yes
macos_show_window_title_in window
# ===== Clipboard =====
clipboard_control write-clipboard write-primary read-clipboard read-primary
clipboard_max_size 512
# ===== Notifications =====
# Kitty sends native macOS notifications on bell (replaces iTerm2 Growl)
# ===== Advanced =====
allow_remote_control yes
listen_on unix:/tmp/kitty-socket
shell_integration enabled no-keyboard
modify_keyboard_shortcuts no
confirm_os_window_close 1
update_check_interval 24
# =============================================================
# KEY MAPPINGS — iTerm2 equivalents
# =============================================================
# -- Shift+Enter → literal newline (matching your iTerm2 global key map) --
map shift+enter send_text all \n
# -- Tabs (like iTerm2) --
map cmd+t new_tab_with_cwd
map cmd+w close_tab
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 cmd+shift+] next_tab
map cmd+shift+[ previous_tab
# -- Splits / Panes (like iTerm2 Cmd+D / Cmd+Shift+D) --
map cmd+d combine : goto_layout splits : launch --cwd=current --location=vsplit
map cmd+shift+d combine : goto_layout splits : launch --cwd=current --location=hsplit
map cmd+shift+w close_window
# -- Navigate between panes (like iTerm2 Cmd+Alt+Arrow) --
map cmd+alt+left neighboring_window left
map cmd+alt+right neighboring_window right
map cmd+alt+up neighboring_window up
map cmd+alt+down neighboring_window down
# -- Resize panes --
map cmd+shift+left resize_window narrower 2
map cmd+shift+right resize_window wider 2
map cmd+shift+up resize_window taller 2
map cmd+shift+down resize_window shorter 2
# -- Toggle pane zoom (like iTerm2 Cmd+Shift+Enter to maximize pane) --
map cmd+shift+enter toggle_layout stack
# -- Font size (like iTerm2 Cmd+/Cmd-) --
map cmd+equal change_font_size all +1.0
map cmd+minus change_font_size all -1.0
map cmd+0 change_font_size all 0
# -- Scrollback --
map cmd+k clear_terminal scrollback active
map cmd+shift+k clear_terminal scroll active
map cmd+f show_scrollback
# -- Broadcast input to all panes (like iTerm2 broadcast input) --
# No built-in; use kitten for this (see broadcast kitten below)
# -- Open scrollback in editor (like iTerm2 "Open in Editor") --
map cmd+shift+g launch --stdin-source=@screen_scrollback --type=overlay $EDITOR
# -- Reload config --
map cmd+shift+r load_config_file
# -- Hints kitten — keyboard-select anything on screen --
map ctrl+shift+p kitten hints
map ctrl+shift+f kitten hints --type path --program -
map ctrl+shift+n kitten hints --type linenum --linenum-action launch --action-alias linenum=cursor --goto-line {line} {file}
# -- Dynamic theme switching --
map cmd+shift+t kitten themes --reload-in=all
# -- Project switcher --
map cmd+p kitten /Users/olegkoval/.config/kitty/project_switcher.py
# -- AI-to-shell kitten --
map ctrl+shift+a kitten /Users/olegkoval/.config/kitty/ai_shell.py
# =============================================================
# STARTUP SESSION (equivalent to iTerm2 "WORK SETUP" arrangement)
# =============================================================
# Create ~/.config/kitty/sessions/work.conf to define your layout:
# kitty --session ~/.config/kitty/sessions/work.conf
# See: https://sw.kovidgoyal.net/kitty/overview/#startup-sessions
# ===== Colors (matching iTerm2 light theme) =====
# Default colors
# foreground #101010
# background #fafafa
# Cursor
# cursor #000000
# Selection
# selection_foreground #000000
# selection_background #b3d7ff
# Black
# color0 #141e1e
# color8 #686868
# Red
# color1 #b43c29
# color9 #dd7975
# Green
# color2 #00c200
# color10 #58e772
# Yellow
# color3 #c7c400
# color11 #ece100
# Blue
# color4 #2743c8
# color12 #a7abc8
# Magenta
# color5 #c040be
# color13 #e17ee1
# Cyan
# color6 #00c5c7
# color14 #60fefe
# White
# color7 #c7c7c7
# color15 #ffffff
# BEGIN_KITTY_THEME
# Base2Tone Heath Dark
include current-theme.conf
# END_KITTY_THEME
import os
import subprocess
import sys
def main(args):
projects_file = os.path.expanduser('~/.config/kitty/projects.txt')
try:
with open(projects_file) as f:
projects = [l.strip() for l in f if l.strip()]
except FileNotFoundError:
print(f'projects.txt not found at {projects_file}', file=sys.stderr)
return None
# fzf reads list from stdin (pipe). We route its UI explicitly to /dev/tty
# so it can render its interactive interface in the kitten overlay window.
# Selection comes back on stdout (captured via PIPE).
with open('/dev/tty', 'wb') as tty:
proc = subprocess.Popen(
['/opt/homebrew/opt/fzf/bin/fzf', '--prompt', 'Project > ', '--height', '40%'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=tty,
)
stdout, _ = proc.communicate('\n'.join(projects).encode())
if proc.returncode != 0:
return None
return stdout.decode().strip() or None
def handle_result(args, answer, target_window_id, boss):
if answer:
path = os.path.expanduser(answer)
name = os.path.basename(path)
boss.new_tab(cwd=path, tab_title=name)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment