Skip to content

Instantly share code, notes, and snippets.

@o-az
Created January 13, 2026 04:44
Show Gist options
  • Select an option

  • Save o-az/f23cfdbc6a7c6afbf24ee1cdf3e6166b to your computer and use it in GitHub Desktop.

Select an option

Save o-az/f23cfdbc6a7c6afbf24ee1cdf3e6166b to your computer and use it in GitHub Desktop.
Kitty Remote Control Protocol Documentation - comprehensive guide for programmatic terminal control

Kitty Remote Control Protocol Documentation

Overview

Kitty's remote control system allows external programs to control kitty terminal instances through a JSON-based protocol. This enables programmatic control over windows, tabs, colors, text, and more.

Source References:


Activation

Remote control must be explicitly enabled. There are three methods:

1. Command-line flag

kitty --allow-remote-control

2. Configuration option in kitty.conf

allow_remote_control yes

3. Socket-based control (recommended for external scripts)

kitty --listen-on unix:/tmp/mykitty

Then connect from any terminal:

kitten @ --to unix:/tmp/mykitty ls

4. Password-based authentication

remote_control_password "mypassword" *

Wire Protocol

Message Format

Commands are sent as JSON wrapped in escape sequences:

<ESC>P@kitty-cmd<JSON><ESC>\

Where <ESC> is byte 0x1b.

JSON Structure

{
  "cmd": "command_name",
  "version": [0, 14, 2],
  "no_response": false,
  "payload": { ... }
}
Field Description
cmd The command name (e.g., ls, send-text, launch)
version Array [major, minor, patch] of kitty version you're targeting
no_response Set true to skip waiting for response
payload Command-specific JSON object

Example: Raw Protocol Usage

# Start kitty with socket
kitty --listen-on unix:/tmp/mykitty &

# Send ls command via raw protocol
printf '\x1bP@kitty-cmd{"cmd":"ls","version":[0,14,2]}\x1b\\' | socat - UNIX-CONNECT:/tmp/mykitty

Encrypted Communication

When using remote_control_password, communication is encrypted using:

  • Key Exchange: Elliptic Curve Diffie-Hellman (X25519)
  • Encryption: AES-256-GCM with authenticated encryption
  • Key Data: Base-85 encoded in KITTY_PUBLIC_KEY environment variable
  • Nonce: Time-based (commands >5 minutes old are rejected)

Encrypted command structure:

{
  "encrypted": "<base64 encrypted data>",
  "iv": "<base64 IV>",
  "tag": "<base64 auth tag>",
  "pubkey": "<base64 client public key>"
}

Async and Streaming Requests

Async Requests

For commands requiring user interaction (e.g., select-window):

{
  "cmd": "select-window",
  "version": [0, 14, 2],
  "async": "unique-random-id",
  "payload": { ... }
}

Cancel with:

{
  "cancel_async": "unique-random-id"
}

Streaming Requests

For large data transfers (e.g., set-background-image):

{
  "cmd": "set-background-image",
  "version": [0, 14, 2],
  "stream": true,
  "stream_id": "unique-stream-id",
  "payload": { "data": "<chunk>" }
}

Send empty chunk to signal end of stream.


Command Reference

Listing & Querying

ls

List all OS windows, tabs, and windows as a JSON tree.

kitten @ ls

Payload fields:

Field Default Description
all_env_vars false Include all environment variables
match None Window match expression
match_tab None Tab match expression
self false Only list current window
output_format json Output format: json or session

get-text

Get text from a window's screen or scrollback.

kitten @ get-text --match id:1

Payload fields:

Field Default Description
match None Window to get text from
extent screen One of: screen, all, selection, first_cmd_output_on_screen, last_cmd_output, last_visited_cmd_output
ansi false Include ANSI formatting codes
cursor None Include cursor position/style
wrap_markers None Add wrap markers
clear_selection false Clear selection after getting
self false Use current window

Window/Tab Management

launch

Create new windows, tabs, or OS windows.

kitten @ launch --type=tab --title="My Tab" bash

Payload fields:

Field Default Description
args [] Command line as array
type window One of: window, tab, os-window, overlay, overlay-main, background
match None Tab to open window in
window_title None Window title
tab_title None Tab title
cwd None Working directory
env [] Environment variables (NAME=VALUE)
keep_focus false Don't switch focus to new window
hold false Keep window open after command exits
location default Position in tab layout
copy_colors false Copy colors from source window
copy_env [] Copy environment from source

Returns: Window ID of newly created window.

close-window

Close a window.

kitten @ close-window --match id:1

focus-window

Focus a specific window.

kitten @ focus-window --match title:vim

resize-window

Resize a window.

kitten @ resize-window --increment 2 --axis horizontal

Sending Input

send-text

Send text to a window's terminal.

kitten @ send-text --match id:1 "Hello, World\n"

Payload fields:

Field Default Description
data required Text as text:... or base64:...
match None Target window
match_tab None Target tab
all false Send to all windows
exclude_active false Skip active window
bracketed_paste disable Wrap in bracketed paste codes
session_id None Broadcast session identifier

send-key

Send key presses to a window.

kitten @ send-key --match id:1 ctrl+c

Payload fields:

Field Default Description
keys required List of key names
match None Target window
all false Send to all windows

Appearance

set-colors

Change terminal colors dynamically.

kitten @ set-colors foreground=white background=black

Payload fields:

Field Default Description
colors required Object mapping color names to RGB integers
match_window None Target window
match_tab None Target tab
all false Apply everywhere
configured false Change configured colors
reset false Reset to startup values

set-background-image

Set window background image.

kitten @ set-background-image /path/to/image.png

Payload fields:

Field Default Description
data required Base64 PNG chunks (max 512 bytes each) or - to remove
match None Target window
layout configured Image layout
all false Apply to all windows

set-spacing

Set window margins and padding.

kitten @ set-spacing margin=20 padding-left=10

Process Control

signal-child

Send signals to child processes.

kitten @ signal-child --match id:1 SIGTERM

Payload fields:

Field Default Description
signals required List of signal names (e.g., SIGTERM, SIGKILL)
match None Target windows

run

Run a command and capture output.

kitten @ run ls -la

Markers

create-marker

Highlight text patterns in a window.

kitten @ create-marker --match id:1 text 1 ERROR

remove-marker

Remove markers from a window.

kitten @ remove-marker --match id:1

Configuration

load-config

Reload configuration.

kitten @ load-config

Payload fields:

Field Default Description
paths [] Config file paths to load
override [] Individual config overrides
ignore_overrides false Skip previous overrides

env

Set environment variables for future child processes.

kitten @ env MY_VAR=value

Matching Windows and Tabs

The --match and --match-tab options use a powerful query syntax:

Match Syntax

field:query

Available Fields

Field Type Description
id numeric Window ID (negative counts from newest: -1 = most recent)
title regex Window title
pid numeric Process ID
cwd regex Current working directory
cmdline regex Command line of running process
num numeric Window position in tab (0-indexed, clockwise from top-left)
env regex Environment variables (format: VAR=value)
var regex User variables
state enum Window state (see below)
neighbor enum Neighbor direction: left, right, top, bottom
session regex Session name
recent numeric Recently active (0 = current, 1 = previous, ...)

State Values

State Description
active Active window in its parent tab
focused The window receiving keyboard input
needs_attention Window requesting attention
parent_active Window's tab is active
parent_focused Window's tab is focused
focused_os_window All windows in focused OS window
self Window where command is run
overlay_parent Window under an overlay

Boolean Operators

Combine conditions with:

  • and - Both must match
  • or - Either must match
  • not - Negate condition

Examples

# Match by ID
kitten @ focus-window --match id:1

# Match by title regex
kitten @ send-text --match title:vim "Hello"

# Match by command line
kitten @ close-window --match cmdline:python

# Match neighbor
kitten @ focus-window --match neighbor:left

# Match by state
kitten @ ls --match state:focused

# Boolean combination
kitten @ focus-window --match "title:vim and state:active"

# Match all windows
kitten @ send-text --match all "broadcast message"

# Recent window
kitten @ focus-window --match recent:1

Data Model and Object Hierarchy

Composition Hierarchy

Kitty Instance (singleton)
└── OS Windows (operating system windows)
    └── Tabs (groups of kitty windows)
        └── Windows (terminal panes)
            ├── Screen (visible content)
            ├── Scrollback buffer
            └── Child process

1. OS Window

An OS Window is a native operating system window. Each kitty process can have multiple OS windows.

Key Properties:

Property Description
id Unique numeric identifier
is_focused Whether this OS window has focus
is_active Whether this is the active OS window
platform_window_id Native window ID (X11/Wayland/macOS)
tabs List of tabs in this OS window
background_opacity Window opacity (0.0-1.0)

2. Tab

A Tab contains one or more kitty windows arranged in a layout.

Key Properties:

Property Description
id Unique numeric identifier
title Tab title (usually from active window)
is_focused Whether this tab is focused
is_active Whether this tab is active
layout Current layout name (tall, grid, splits, etc.)
layout_opts Layout-specific options
enabled_layouts List of available layouts
windows List of windows in this tab
groups Window groupings
active_window_history Stack of recently active window IDs

3. Window (Kitty Window)

A Window is a single terminal pane running a child process.

Key Properties:

Property Description
id Unique numeric identifier
title Window title
is_focused Whether this window is focused
is_active Whether this window is active in its tab
is_self Whether this is the window running the command
pid Process ID of child
cwd Current working directory
cmdline Command line of running process
env Environment variables (diff from parent)
columns Terminal width in columns
lines Terminal height in lines
at_prompt Whether shell is at prompt (requires shell integration)
created_at Creation timestamp
foreground_processes List of foreground process info

4. Layout

A Layout arranges windows within a tab. Available layouts:

Layout Description
tall Main window left, others stacked right
fat Main window top, others side-by-side bottom
grid Windows in a grid
horizontal All windows side-by-side
vertical All windows stacked
splits Arbitrary horizontal/vertical splits
stack Only active window visible (others hidden)

Example JSON from kitten @ ls

[
  {
    "id": 1,
    "is_focused": true,
    "is_active": true,
    "platform_window_id": 25176,
    "background_opacity": 1.0,
    "tabs": [
      {
        "id": 1,
        "title": "fish - ~/projects",
        "is_focused": true,
        "is_active": true,
        "layout": "tall",
        "layout_opts": {
          "bias": 50,
          "full_size": 1,
          "mirrored": "n"
        },
        "enabled_layouts": ["tall:bias=50", "fat:bias=50", "grid", "splits"],
        "active_window_history": [1, 2],
        "windows": [
          {
            "id": 1,
            "title": "fish",
            "is_focused": true,
            "is_active": true,
            "is_self": true,
            "pid": 12345,
            "cwd": "/Users/alice/projects",
            "cmdline": ["/opt/homebrew/bin/fish"],
            "columns": 120,
            "lines": 40,
            "at_prompt": true,
            "env": {
              "KITTY_WINDOW_ID": "1"
            },
            "foreground_processes": [
              {
                "pid": 12345,
                "cwd": "/Users/alice/projects",
                "cmdline": ["fish"]
              }
            ]
          }
        ]
      }
    ]
  }
]

Environment Variables

Set by Kitty

Variable Description
KITTY_WINDOW_ID Current window's numeric ID
KITTY_PID Kitty process ID
KITTY_PUBLIC_KEY Public key for encrypted remote control
KITTY_LISTEN_ON Socket path (when enabled)
TERM Terminal type (xterm-kitty)
TERMINFO Path to terminfo database
COLORTERM Set to truecolor

Influence Kitty Behavior

Variable Description
KITTY_CONFIG_DIRECTORY Config file location
KITTY_CACHE_DIRECTORY Cache directory
KITTY_RC_PASSWORD Remote control password

Watchers (Event Callbacks)

Create Python scripts that respond to window events.

Setup

  1. Create ~/.config/kitty/mywatcher.py:
def on_resize(boss, window, data):
    # Called when window is resized
    pass

def on_focus_change(boss, window, data):
    # Called when focus changes
    pass

def on_close(boss, window, data):
    # Called when window closes
    pass

def on_set_user_var(boss, window, data):
    # Called when user variable is set
    pass

def on_title_change(boss, window, data):
    # Called when title changes
    pass

def on_cmd_startstop(boss, window, data):
    # Called when command starts/stops (requires shell integration)
    pass
  1. Launch with watcher:
kitten @ launch --watcher mywatcher.py

Or set global watcher in kitty.conf:

watcher mywatcher.py

Calling Remote Control from Watchers

def on_focus_change(boss, window, data):
    boss.call_remote_control(window, ('set-colors', '--match', f'id:{window.id}', 'background=#000000'))

Common Patterns

Pattern 1: Run Command and Capture Output

# Launch window, run command, get output
win_id=$(kitten @ launch --type=window --keep-focus --hold -- sh -c 'your_command')
sleep 1
kitten @ get-text --match "id:$win_id"
kitten @ close-window --match "id:$win_id"

Pattern 2: Broadcast to All Windows

kitten @ send-text --all "Message to all windows\n"

Pattern 3: Dynamic Color Scheme

# Dark mode
kitten @ set-colors --all background=#1a1a2e foreground=#eaeaea

# Light mode
kitten @ set-colors --all background=#ffffff foreground=#1a1a1a

Pattern 4: Script-based Window Management

#!/bin/bash
# Create development layout

# Launch editor in main window
editor_id=$(kitten @ launch --type=tab --title="Editor" nvim)

# Launch terminal below
term_id=$(kitten @ launch --type=window --location=hsplit fish)

# Launch log viewer on right
log_id=$(kitten @ launch --type=window --location=vsplit tail -f /var/log/app.log)

Pattern 5: Persistent Named Session

# Check if socket exists
if [ -S /tmp/myproject-kitty ]; then
    kitten @ --to unix:/tmp/myproject-kitty focus-window
else
    kitty --listen-on unix:/tmp/myproject-kitty --session ~/.config/kitty/sessions/myproject.session &
fi

Key Differences from tmux Control Mode

Feature tmux Control Mode Kitty Remote Control
Protocol Line-based text JSON over escape sequences
Activation tmux -C flag Config option or socket
Security None built-in Password-based with encryption
Streaming Output notifications Chunked streaming with stream_id
Object model Sessions → Windows → Panes OS Windows → Tabs → Windows
Matching Window/pane IDs Rich query DSL with regex
Events Push notifications (%output, etc.) Python watchers

Integration Notes for Client Developers

  1. Version compatibility: Always specify a version array matching or below the target kitty version
  2. Handle async: Some commands (like select-window) require async handling with unique IDs
  3. Streaming large data: Use stream and stream_id for large payloads, send empty chunk to end
  4. Encryption: When using passwords, implement ECDH key exchange and AES-256-GCM encryption
  5. Time sensitivity: Encrypted commands have a 5-minute validity window
  6. Match syntax: Use the query DSL for flexible window targeting
  7. Environment detection: Check KITTY_WINDOW_ID to detect if running inside kitty

Quick Reference: Common Commands

# List everything
kitten @ ls

# Get text from screen
kitten @ get-text --extent screen

# Send text to window
kitten @ send-text --match id:1 "Hello\n"

# Create new tab
kitten @ launch --type=tab --cwd current

# Focus window by title
kitten @ focus-window --match title:vim

# Change colors
kitten @ set-colors background=#1a1a2e

# Signal child process
kitten @ signal-child --match id:1 SIGINT

# Interactive shell
kitten @
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment