# Command-Line Interface

Jay provides a comprehensive CLI for controlling the compositor, managing
displays, input devices, clients, and more. All subcommands communicate with
the running compositor over the Wayland protocol unless otherwise noted.

> [!TIP]
> Generate shell completions for tab-completion support:
>
> ```shell
> ~$ jay generate-completion bash > ~/.local/share/bash-completion/completions/jay
> ~$ jay generate-completion zsh > ~/.zfunc/_jay
> ~$ jay generate-completion fish > ~/.config/fish/completions/jay.fish
> ~$ jay generate-completion elvish  # pipe to appropriate location
> ~$ jay generate-completion powershell  # pipe to appropriate location
> ```

Every subcommand accepts a global `--log-level` option (`trace`, `debug`,
`info`, `warn`, `error`, `off`) that controls the verbosity of the CLI tool itself.

---

## JSON Output

Most query and status commands can output machine-readable JSON instead of
human-readable text. Pass the global `--json` flag before the subcommand:

```shell
~$ jay --json randr
~$ jay --json clients
~$ jay --json idle
```

Each command prints one or more JSON objects, one per line (JSONL format). This
makes it easy to process with tools like `jq`:

```shell
~$ jay --json randr | jq '.drm_devices[].connectors[].name'
~$ jay --json clients | jq 'select(.pid != null) | .pid'
```

By default, fields that are empty arrays, `null`, or `false` are omitted from
the output to reduce noise. To include every field, pass `--all-json-fields`:

```shell
~$ jay --all-json-fields --json randr
```

### Supported Commands

The following commands support `--json`:

`jay clients`
: One JSON object per client.

`jay color-management status`
: Color management enabled/available status.

`jay config path`
: The config file path as a JSON string.

`jay idle status`
: Idle interval, grace period, and inhibitors.

`jay input show`, `jay input seat <seat> show`, `jay input device <id> show`
: Seats and input devices with all properties.

`jay log --path`
: The log file path as a JSON string.

`jay pid`
: The compositor PID as a JSON number.

`jay randr show`
: DRM devices, connectors, outputs, modes, and display properties.

`jay seat-test`
: Streaming JSONL -- one JSON object per input event (key, pointer, touch,
  gesture, tablet, switch).

`jay tree query`
: One JSON object per root node, with children nested recursively.

`jay version`
: The version string as a JSON value.

`jay xwayland status`
: Xwayland scaling mode and implied scale.

> [!TIP]
> Mutating commands (e.g., `jay idle set`, `jay randr output ... enable`)
> produce no output, so `--json` has no effect on them.

---

## Running

### `jay run`

Start the compositor.

```shell
~$ jay run
```

Optionally specify which backends to try (comma-separated, tried in order):

```shell
~$ jay run --backends x11,metal,headless
```

The default order is `x11,metal`. The first backend that can be started is
used. `metal` is the native DRM/KMS backend for bare-metal sessions.

### `jay quit`

Stop the running compositor.

```shell
~$ jay quit
```

### `jay pid`

Print the PID of the running compositor.

```shell
~$ jay pid
```

### `jay version`

Print the Jay version.

```shell
~$ jay version
```

---

## Configuration

### `jay config init`

Generate a configuration file pre-populated with all defaults.

```shell
~$ jay config init
```

If a config already exists, pass `--overwrite` to replace it (the old file is
backed up):

```shell
~$ jay config init --overwrite
```

> [!IMPORTANT]
> Once a config file exists, the entire built-in default configuration is
> replaced -- not merged. An empty config file means no shortcuts, no startup
> actions, nothing. Always use `jay config init` to start with a working
> configuration.

### `jay config path`

Print the path to the config file.

```shell
~$ jay config path
```

### `jay config open-dir`

Open the configuration directory with `xdg-open`.

```shell
~$ jay config open-dir
```

---

## Display & Graphics

All display and GPU commands live under `jay randr`.

### Showing Current Settings

```shell
~$ jay randr
~$ jay randr show
~$ jay randr show --modes      # include all available modes
~$ jay randr show --formats    # include all available framebuffer formats
```

### GPU / Card Commands

Set the primary (render) GPU:

```shell
~$ jay randr card card0 primary
```

Set the graphics API:

```shell
~$ jay randr card card0 api vulkan
~$ jay randr card card0 api opengl
```

Toggle direct scanout:

```shell
~$ jay randr card card0 direct-scanout enable
~$ jay randr card card0 direct-scanout disable
```

Adjust the page-flip margin (in milliseconds, default 1.5):

```shell
~$ jay randr card card0 timing set-flip-margin 1.5
```

### Output Commands

Enable or disable an output:

```shell
~$ jay randr output DP-1 enable
~$ jay randr output DP-1 disable
```

Set the position:

```shell
~$ jay randr output DP-1 position 1920 0
```

Set the scale (fractional scaling supported):

```shell
~$ jay randr output DP-1 scale 1.5
~$ jay randr output DP-1 scale --round-to-float 1.333
```

Set the mode (width, height, refresh rate in Hz):

```shell
~$ jay randr output DP-1 mode 2560 1440 144.0
```

Set the transform:

```shell
~$ jay randr output DP-1 transform rotate-90
~$ jay randr output DP-1 transform none
```

Available transforms: `none`, `rotate-90`, `rotate-180`, `rotate-270`, `flip`,
`flip-rotate-90`, `flip-rotate-180`, `flip-rotate-270`.

Override the non-desktop setting:

```shell
~$ jay randr output DP-1 non-desktop true
~$ jay randr output DP-1 non-desktop default
```

Configure VRR (variable refresh rate):

```shell
~$ jay randr output DP-1 vrr set-mode always
~$ jay randr output DP-1 vrr set-mode variant3
~$ jay randr output DP-1 vrr set-cursor-hz 240
~$ jay randr output DP-1 vrr set-cursor-hz none
```

VRR modes: `never`, `always`, `variant1` (one or more fullscreen apps),
`variant2` (single fullscreen app), `variant3` (single fullscreen app with
game/video content type). Pass `none` to `set-cursor-hz` to remove the cursor
Hz cap.

Configure tearing:

```shell
~$ jay randr output DP-1 tearing set-mode variant3
```

Tearing modes: `never`, `always`, `variant1` (one or more applications
displayed fullscreen), `variant2` (single application displayed fullscreen),
`variant3` (default -- single displayed application that requested tearing).

Set the framebuffer format:

```shell
~$ jay randr output DP-1 format set xrgb8888
```

Set the output color space and EOTF (for HDR):

```shell
~$ jay randr output DP-1 colors set bt2020 pq
~$ jay randr output DP-1 colors set default default
```

Set the brightness (in cd/m^2, or `default`):

```shell
~$ jay randr output DP-1 brightness 203
~$ jay randr output DP-1 brightness default
```

Set the blend space:

```shell
~$ jay randr output DP-1 blend-space linear
~$ jay randr output DP-1 blend-space srgb
```

Enable or disable native gamut usage:

```shell
~$ jay randr output DP-1 use-native-gamut true
~$ jay randr output DP-1 use-native-gamut false
```

### Virtual Outputs

```shell
~$ jay randr virtual-output create my-virtual-display
~$ jay randr virtual-output remove my-virtual-display
```

---

## Input

All input commands live under `jay input`.

### Showing Input Devices

```shell
~$ jay input
~$ jay input show
~$ jay input show -v    # verbose output with device details
```

### Seat Commands

Show seat information:

```shell
~$ jay input seat default show
~$ jay input seat default show -v
```

Set keyboard repeat rate (repeats per second, initial delay in ms):

```shell
~$ jay input seat default set-repeat-rate 25 600
```

Set the keymap from RMLVO names:

```shell
~$ jay input seat default set-keymap-from-names -l de
~$ jay input seat default set-keymap-from-names -l us -v intl -o compose:ralt
```

Set the keymap from a file (or stdin):

```shell
~$ jay input seat default set-keymap /path/to/keymap.xkb
```

Retrieve the current keymap:

```shell
~$ jay input seat default keymap > current.xkb
```

Toggle hardware cursor:

```shell
~$ jay input seat default use-hardware-cursor true
~$ jay input seat default use-hardware-cursor false
```

Set cursor size:

```shell
~$ jay input seat default set-cursor-size 24
```

Configure the simple (XCompose-based) input method:

```shell
~$ jay input seat default simple-im enable
~$ jay input seat default simple-im disable
~$ jay input seat default simple-im reload
```

### Device Commands

Show device information:

```shell
~$ jay input device 42 show
```

Set acceleration profile and speed:

```shell
~$ jay input device 42 set-accel-profile flat
~$ jay input device 42 set-accel-profile adaptive
~$ jay input device 42 set-accel-speed -0.5
```

Configure tap behavior:

```shell
~$ jay input device 42 set-tap-enabled true
~$ jay input device 42 set-tap-drag-enabled true
~$ jay input device 42 set-tap-drag-lock-enabled false
```

Set left-handed mode:

```shell
~$ jay input device 42 set-left-handed true
```

Set natural scrolling:

```shell
~$ jay input device 42 set-natural-scrolling true
```

Set pixels per scroll-wheel step:

```shell
~$ jay input device 42 set-px-per-wheel-scroll 30.0
```

Set the transform matrix (2x2):

```shell
~$ jay input device 42 set-transform-matrix 1.0 0.0 0.0 1.0
```

Set the calibration matrix (2x3, for touchscreens):

```shell
~$ jay input device 42 set-calibration-matrix 1.0 0.0 0.0 0.0 1.0 0.0
```

Set the click method:

```shell
~$ jay input device 42 set-click-method clickfinger
~$ jay input device 42 set-click-method button-areas
~$ jay input device 42 set-click-method none
```

Toggle middle button emulation:

```shell
~$ jay input device 42 set-middle-button-emulation true
```

Set a per-device keymap:

```shell
~$ jay input device 42 set-keymap /path/to/keymap.xkb
~$ jay input device 42 set-keymap-from-names -l de
~$ jay input device 42 keymap > device.xkb
```

Attach / detach a device from a seat:

```shell
~$ jay input device 42 attach default
~$ jay input device 42 detach
```

Map a device to a specific output:

```shell
~$ jay input device 42 map-to-output DP-1
~$ jay input device 42 remove-mapping
```

---

## Idle & Locking

### `jay idle`

Show idle status, including the current interval, grace period, and active
inhibitors:

```shell
~$ jay idle
~$ jay idle status
```

### `jay idle set`

Set the idle interval. Durations can be specified in flexible formats:

```shell
~$ jay idle set 10m
~$ jay idle set 1m 30s
~$ jay idle set disabled
```

### `jay idle set-grace-period`

Set the grace period (screens go black but are not locked/disabled):

```shell
~$ jay idle set-grace-period 30s
~$ jay idle set-grace-period disabled
```

### `jay unlock`

Unlock the compositor. This is useful when the screen locker crashes and the
session remains locked. Run it from another TTY or via SSH. You must set
`WAYLAND_DISPLAY` to the socket of the Jay compositor:

```shell
~$ WAYLAND_DISPLAY=wayland-1 jay unlock
```

---

## Logging

### `jay log`

Open the log file in `less`:

```shell
~$ jay log
~$ jay log -f        # follow mode (like tail -f)
~$ jay log -e        # jump to end of log
~$ jay log --path    # print the log file path instead
```

### `jay set-log-level`

Change the log level at runtime:

```shell
~$ jay set-log-level debug
~$ jay set-log-level info
```

Available levels: `trace`, `debug`, `info`, `warn`, `error`, `off`.

---

## Screenshots

### `jay screenshot`

Take a screenshot of the entire display:

```shell
~$ jay screenshot
~$ jay screenshot --format png
~$ jay screenshot --format qoi
~$ jay screenshot my-screenshot.png
```

If no filename is given, the screenshot is saved as
`%Y-%m-%d-%H%M%S_jay.<ext>` in the current directory. The filename supports
strftime format specifiers.

---

## Clients & Windows

### `jay clients`

List all connected clients:

```shell
~$ jay clients
~$ jay clients show all
```

Show a specific client by ID:

```shell
~$ jay clients show id 42
```

Interactively select a window and show its client:

```shell
~$ jay clients show select-window
```

Kill a client by ID:

```shell
~$ jay clients kill id 42
```

Interactively select a window and kill its client:

```shell
~$ jay clients kill select-window
```

### `jay tree query`

Inspect the compositor's surface tree:

```shell
~$ jay tree query root
~$ jay tree query -r root                    # recursive
~$ jay tree query -r --all-clients root      # show client details for every node
~$ jay tree query workspace-name main
~$ jay tree query select-workspace
~$ jay tree query select-window
```

---

## Xwayland

### `jay xwayland`

Show Xwayland status (scaling mode, implied scale):

```shell
~$ jay xwayland
~$ jay xwayland status
```

### `jay xwayland set-scaling-mode`

```shell
~$ jay xwayland set-scaling-mode default
~$ jay xwayland set-scaling-mode downscaled
```

In `downscaled` mode, X11 windows are rendered at the highest integer scale and
then downscaled, which can improve sharpness on HiDPI displays.

---

## Color Management

### `jay color-management`

Show color management status:

```shell
~$ jay color-management
~$ jay color-management status
```

### `jay color-management enable / disable`

```shell
~$ jay color-management enable
~$ jay color-management disable
```

---

## Other Commands

### `jay seat-test`

Test input events from a seat. Prints all keyboard, pointer, touch, gesture,
tablet, and switch events to stdout:

```shell
~$ jay seat-test
~$ jay seat-test default
~$ jay seat-test -a              # test all seats simultaneously
```

### `jay generate-completion`

Generate shell completion scripts:

```shell
~$ jay generate-completion bash
~$ jay generate-completion zsh
~$ jay generate-completion fish
~$ jay generate-completion elvish
~$ jay generate-completion powershell
```
