kitty-rc
A Rust library for controlling the kitty terminal emulator via its remote control protocol
About
kitty-rc is a Rust library that provides a type-safe, async interface for controlling the kitty terminal emulator through its remote control protocol. It uses Unix domain sockets for communication and supports all major kitty remote control commands.
Features
- Comprehensive Command Support: All major kitty remote control commands organized into modules
- Type-Safe Builder API: Fluent builder pattern for client setup and all commands
- Async-First: Built on tokio for asynchronous I/O
- Single Connection: Connect once at startup, reuse for all commands
- Password Authentication: Secure encrypted communication using ECDH X25519 key exchange and AES-256-GCM
- Error Handling: Detailed error types for protocol, command, connection, and encryption errors
- Streaming Support: Automatic chunking for large payloads (e.g., background images)
- Async Commands: Support for async operations with unique ID generation
- Comprehensive Testing: 143 unit tests ensuring reliability
Installation
Add this to your Cargo.toml:
[]
= "0.4.0"
= { = "1.0", = ["full"] }
Usage
Basic Setup
use Kitty;
async
Connection with Password
When kitty is configured with remote_control_password, password authentication provides encrypted communication.
From within kitty
Note: Password authentication automatically works when your application is launched by kitty or running within a kitty window, because kitty exposes its public key via KITTY_PUBLIC_KEY environment variable only to processes it launches.
use Kitty;
async
From standalone clients
For standalone clients (not launched by kitty), you have two options:
Option 1: Automatic database query (recommended)
If you're using the kitty-pubkey-db shell integration, KittyBuilder will automatically query the database for the public key when:
- A password is provided
- No explicit
public_key()is set KITTY_PUBLIC_KEYenvironment variable is not set
The socket path must contain the kitty PID (e.g., /tmp/kitty-12345.sock or /run/user/1000/kitty/kitty-12345.sock).
use Kitty;
async
Option 2: Explicit public key
For standalone clients (not launched by kitty), you can provide the public key explicitly using the public_key() method. The public key can be obtained from kitty's public key database (see kitty-pubkey-db binary).
use Kitty;
async
The encryption uses kitty's protocol:
- X25519 ECDH key exchange with kitty's public key (from KITTY_PUBLIC_KEY or provided via public_key())
- Client generates ephemeral keys per command
- AES-256-GCM authenticated encryption
- SHA-256 derived shared secret
For detailed specifications of the encrypted communication protocol, see Encrypted communication.
Listing Windows
use ;
let cmd = new
.self_window
.build?;
let response = kitty.execute.await?;
let instances = parse_response?;
for instance in &instances
Sending Text to Windows
use SendTextCommand;
let cmd = new
.match_spec
.build?;
kitty.send_command.await?;
Creating New Windows
use NewWindowCommand;
let cmd = new
.args
.cwd
.title
.build?;
kitty.send_command.await?;
Setting Font Size
use SetFontSizeCommand;
// Set absolute font size
let cmd = new
.all
.build?;
kitty.execute.await?;
// Increment font size
let cmd = new
.increment_op
.build?;
kitty.execute.await?;
// Decrement font size
let cmd = new
.increment_op
.build?;
kitty.execute.await?;
Setting Background Opacity
use SetBackgroundOpacityCommand;
let cmd = new
.all
.build?;
kitty.send_command.await?;
Streaming Large Data
use SetBackgroundImageCommand;
let large_image_data = "..."; // Large base64 string
let cmd = new.build?;
// send_all automatically handles chunking for large payloads
kitty.send_all.await?;
Or to get a response:
let response = kitty.execute_all.await?;
Command Modules
Tab Management (commands::tab)
CloseTabCommand- Close tabsDetachTabCommand- Detach tabs to different OS windowsFocusTabCommand- Focus a specific tabSetTabTitleCommand- Set tab title
Layout Management (commands::layout)
GotoLayoutCommand- Switch to a specific layoutSetEnabledLayoutsCommand- Set available layoutsLastUsedLayoutCommand- Switch to last used layout
Window Management (commands::window)
CloseWindowCommand- Close windowsCreateMarkerCommand- Create scroll markersDetachWindowCommand- Detach windowsFocusWindowCommand- Focus a windowGetTextCommand- Extract text from windowsLsCommand- List windows and tabs (supports structured response parsing)NewWindowCommand- Create new windowsRemoveMarkerCommand- Remove scroll markersResizeWindowCommand- Resize windowsScrollWindowCommand- Scroll window contentSelectWindowCommand- Async window selectionSendKeyCommand- Send keyboard shortcutsSendTextCommand- Send text to windowsSetWindowLogoCommand- Set window logoSetWindowTitleCommand- Set window title
Process Management (commands::process)
DisableLigaturesCommand- Disable font ligaturesEnvCommand- Set environment variablesKittenCommand- Run kitty kittensLaunchCommand- Launch new windows with comprehensive optionsLoadConfigCommand- Load configuration filesResizeOSWindowCommand- Resize OS windowsRunCommand- Run commands with streaming supportSetUserVarsCommand- Set user variablesSignalChildCommand- Send signals to child processes
Style and Appearance (commands::style)
GetColorsCommand- Get current colorsSetBackgroundImageCommand- Set background image (supports streaming)SetBackgroundOpacityCommand- Set background opacitySetColorsCommand- Set color schemeSetFontSizeCommand- Set font size (absolute or increment/decrement)SetSpacingCommand- Set window padding/spacingSetTabColorCommand- Set tab colors
Note: Kitty's remote protocol does not include a
get-font-sizecommand. To retrieve the current font size, read it from~/.config/kitty/kitty.conf.
Response Types
The library provides structured types for parsing kitty responses:
Window Information
use ;
let response = kitty.execute.await?;
let instances = parse_response?;
for instance in &instances
The WindowInfo struct includes all fields returned by kitty:
- Window metadata:
id,title,pid,cwd,cmdline - State:
is_active,is_focused,is_self,at_prompt,in_alternate_screen - Terminal:
columns,lines,created_at - Processes:
foreground_processes,env,user_vars - Command:
last_cmd_exit_status,last_reported_cmdline
The TabInfo struct includes tab-level information:
- Tab metadata:
id,title - State:
is_active,is_focused,active_window_history - Layout:
layout,enabled_layouts,layout_opts,layout_state - Groups:
groups(window grouping information)
The OsInstance struct includes OS-level information:
- OS metadata:
id,wm_class,wm_name - State:
is_active,is_focused,last_focused - Display:
background_opacity,platform_window_id
Async and Streaming
The library supports async commands and streaming for large payloads:
Async Commands
use SelectWindowCommand;
use KittyMessage;
let async_id = generate_unique_id;
let cmd = new
.title
.async_id
.build?;
Streaming
Large payloads (>4096 bytes) can be sent using the helper methods that automatically handle chunking:
let message = cmd.build?;
client.send_all.await?; // Automatically chunks if needed
Or to get a response:
let response = client.execute_all.await?;
The send_all and execute_all methods automatically detect if a message needs streaming and handle chunking internally, so you don't need to manually check or split payloads.
Error Handling
kitty-rc provides detailed error types:
use ;
match result
Enabling Remote Control
To use kitty-rc, you must enable remote control in kitty. The library provides a helper script to configure kitty securely with password authentication.
Quick Setup
Run the included setup script:
This script will:
- Generate a random 48-character password in
~/.config/kitty/rc.password - Create
~/.config/kitty/rc.confwith remote control configuration - Add
include rc.confto~/.config/kitty/kitty.confif not present - Set up a socket in the XDG runtime directory at
kitty/kitty-{kitty_pid}.sock
Manual Configuration
To manually configure kitty for remote control, create ~/.config/kitty/rc.conf:
# Enable password-based remote control
allow_remote_control password
remote_control_password "$(cat ~/.config/kitty/rc.password)"
# Listen on socket in XDG runtime directory
listen_on unix:${XDG_RUNTIME_DIR}/kitty/kitty-{kitty_pid}.sock
Then add to ~/.config/kitty/kitty.conf:
include rc.conf
This script will:
- Generate a random 48-character password in
~/.config/kitty/rc.password - Add remote control configuration to
~/.config/kitty/kitty.conf - Set up a socket in the XDG runtime directory at
kitty/kitty-{pid}.sock - Fail if any remote control settings are already configured
Manual Configuration
To manually configure kitty for remote control, add to ~/.config/kitty/kitty.conf:
# Enable password-based remote control
allow_remote_control password
remote_control_password "$(cat ~/.config/kitty/rc.password)"
# Listen on socket in XDG runtime directory
listen_on unix:${XDG_RUNTIME_DIR}/kitty/kitty-{kitty_pid}.sock
Generate a secure password:
Restart kitty after making changes.
Socket Configuration
kitty-rc communicates with kitty via Unix domain sockets. The default socket location varies by system:
- With the helper script:
$XDG_RUNTIME_DIR/kitty/kitty-{kitty_pid}.sock - Linux/macOS:
$TMPDIR/kitty-*or/tmp/kitty-* - You can also specify custom socket paths
Testing
Run the test suite:
All 146 tests pass successfully.
Examples
See src/bin/list_windows.rs for a complete example of listing kitty windows and their processes.
Use scripts/enable-rc.sh to quickly enable remote control in your kitty configuration.
Contributing
Contributions are welcome! Please read the project's AGENTS.md for development guidelines.
License
[Specify your license here]
Related
- kitty terminal emulator
- kitty remote control protocol documentation
- kitty remote control protocol specification
Acknowledgments
Built with: