shikane
Date: 2026-03-18

# NAME

shikane - configuration file

# DESCRIPTION

shikane uses the TOML file format for its configuration file and contains an array of profiles. Each profile is a table containing an array of output tables.

The words “output”, “display” and “monitor” can be used interchangeably. In the text below, however, a distinction is made between “display” and “output”. A “display” refers to a currently connected monitor and an “output” refers to a table in the config file. The same goes for “mode” and “mode” respectively. (Please note the font weight.)

shikane selects possible profiles automatically at startup and when a change in the set of currently connected displays occurs. A profile is taken into consideration if every currently connected display can be matched to at least one output and no output is unmatched.
A display matches an output if:

- the search parameter matches against the properties of the display (see also OUTPUT FIELDS below)
- AND the display supports the mode that is specified in the output table.

After assembling a list of possible profiles shikane generates all variants of every profile. Once all variants have been verified and sorted by exactness, shikane tries to apply them one after the other until one succeeds or there are no variants left to try.

Variants are slightly different versions of the same profile.
For example, a given display has a set of supported modes: 1920x1080@60Hz and 1920x1080@50Hz. If the mode in the config.toml is specified as “1920x1080” both modes would fit the specification. Instead of choosing just one mode and using that, shikane takes both into account by generating two variants based on the same profile. One variant uses the 1920x1080@60Hz mode and the other variant uses the 1920x1080@50Hz mode.
The same goes for the search parameter. If multiple (display,output,mode)-combinations are possible, shikane generates variants with all of them.

You don’t need to write the configuration file by hand. You can use any tool to arrange the displays however you want and then use the export command of shikanectl(1). It will generate the config for you.

# FORMAT

timeout = timeout

  Optional. shikane will wait the specified timeout (in milliseconds) whenever a change is detected. Usually you should not set this as it slows down shikane. Is by default 0.

[[profile]]

  Optional. Starts a new profile table. A name must be specified. See PROFILE FIELDS for details.

## PROFILE FIELDS

name = "name"

  Mandatory. Specifies the name of the profile.

[[profile.output]]

  Mandatory. Adds an output table to the profile. Contains parameters used to configure a display. See OUTPUT FIELDS for details.

  On sway(1) for example, display names and descriptions can be obtained via swaymsg -t get_outputs.

exec = [ "command", … ]

  Optional. An exec array contains a set of commands that are executed when the profile was successfully applied. The order of execution is not guaranteed to be preserved. The name of the profile can be retrieved from the $SHIKANE_PROFILE_NAME environment variable.

## OUTPUT FIELDS

A display has, among others, the attributes name, vendor, model, serialnumber and description and may look like this: “DP-1”, “Company Foo”, “FooHD-24”, “12345678”, “Something Foo Something Bar”

search = "pattern"

search = "[kind]pattern"

search = "[[attrs]kind]pattern"

search = [ "[[attrs]kind]pattern", … ]

  Mandatory. This field consists of 3 parts. The attribute list attrs at the beginning, the search kind kind in the middle, and the pattern at the end.

  The attribute list attrs defines which attributes will be compared with the pattern and how they are weighted. It is a sequence of letters from the set {dnmvs}. The letters correspond to the first letters of the above listed attributes. Each attribute should not be used more than once per search field. The first attribute has the highest/best weight, the last attribute has the lowest/worst weight. For a single search to be considered applicable, all attributes must match the pattern.

  The search kind kind can be one of {=/%}. The 3 search kinds — regex(/), substring(%), full text(=) — define how the pattern is compared with each attribute in the attrs list. With full text comparison, the given attributes are compared with the pattern for equality. With substring comparison, the given attributes have to contain the pattern as a substring. The weight is calculated by dividing the lengths of the pattern and attribute strings. Equal lengths will rank the same as full text comparison. With regex comparison, the pattern is interpreted as a regular expression. regex comparison will always rank lower than the other two search kinds.

  The attribute list and the search kind are optional. If unspecified search kind defaults to full text comparison and shikane tries to find at least one matching attribute.

  Alternatively, several searches, up to a maximum of 5, may be specified in an array.

enable = true | false

  Mandatory. Enables or disables the matched display.

exec = [ "command", … ]

  Optional. An exec array contains a set of commands that are executed when the profile was successfully applied. The order of execution is not guaranteed to be preserved. The name of the display can be retrieved from the $SHIKANE_OUTPUT_NAME environment variable.

The mode, position, scale, transform and adaptive_sync options will only change the respective properties of the display if they are specified (e.g. the scaling of a display will not be changed if the scale field is not present).

mode = "best" | "preferred"

mode = "[!]widthxheight[@rate[Hz]]"

mode = { width = width, height = height, refresh = rate[, custom = true | false] }

  Optional. Configures the matched display to use the matched mode. Modes are a combination of width and height (in pixels) and a refresh rate (in Hz) that your display can be configured to use. The refresh rate may also be a floating point number. A display will not be matched against an output if the display does not support the specified mode.

  A parameterized mode can optionally be declared as custom by prefixing an exclamation mark (!). In this case, shikane will not try to find a mode with the same parameters and will just send the provided values to the compositor.

  Setting mode to best or preferred instructs shikane to choose the mode itself. The best mode is determined by shikane as the mode with the highest pixel count, width, height and refresh rate. Most displays announce a mode that they prefer. If mode is set to preferred, shikane will select the preferred mode if it exists. Otherwise, the best mode is chosen as a fallback.

position = "x,y"

  Optional. Places the display at the specified position in the global coordinate space.

scale = factor

  Optional. Scales the display by the specified floating point factor.

transform = "transform"

  Optional. Sets the display transform. May be one of 90, 180, 270 for a rotation; or flipped, flipped-90, flipped-180, flipped-270 for a flip and a rotation; or normal for no transform.

adaptive_sync = true | false

  Optional. Enables or disables adaptive synchronization for the display (also known as VRR, Variable Refresh Rate).

# EXAMPLES

The indentations are not necessary and are used here only to illustrate the hierarchy.

    [[profile]]
    name = "Company Foo with one vertical display"
        [[profile.output]]
        search = "v=Company Foo"
        enable = true
        mode = "1920x1080@50Hz"
        position = "0,0"
        scale = 1.3

        [[profile.output]]
        search = "n/HDMI-[ABC]-[1-9]"
        enable = true
        exec = [ "echo This is output $SHIKANE_OUTPUT_NAME" ]
        position = "1920,0"
        transform = "270"
            [profile.output.mode]
            width = 2560
            height = 1440
            refresh = 75

    [[profile]]
    name = "custom DP-[1-9] flip"
    exec = [ "echo This is an unusual display" ]
        [[profile.output]]
        search = "/DP-[1-9]"
        enable = true
        transform = "flipped"
        position = "0,0"
        mode = "!2000x1500@55.194Hz"

A laptop has a builtin display that is always connected.

    [[profile]]
    name = "laptop builtin"
        [[profile.output]]
        search = "eDP-1"
        enable = true

    [[profile]]
    name = "no builtin + HDMI"
        [[profile.output]]
        search = "n=eDP-1"
        enable = false

        [[profile.output]]
        search = "n=HDMI-A-1"
        mode = "best"
        enable = true

shikane allows you to specifiy multiple searches. This way profiles can be as specific as possible.

    [[profile]]
    name = "home setup"
        [[profile.output]]
        search = "n=eDP-1"
        enable = false

        [[profile.output]]
        search = [ "n=HDMI-A-1", "s=1234VBAM", "m=1QX04Z", "v=specific company" ]
        enable = true

        [[profile.output]]
        search = "smv=1234abcd"
        enable = true

On sway(1) for example, exec can be used to move workspaces to the desired display:

    [[profile]]
    name = "double monitor"
    exec = [
        "swaymsg workspace 1, move workspace to eDP-1",
        "swaymsg workspace 2, move workspace to DP-1" ]
    output = [
        {search = "eDP-1", enable = true},
        {search = "DP-1", enable = true} ]

shikane provides the $SHIKANE_PROFILE_NAME variable in the environment of the executed processes of the profile.exec array and the $SHIKANE_OUTPUT_NAME variable in the environment of the output.exec processes. If you are using sway(1), the last variable is especially useful in conjunction with swayws.

    [[profile]]
    name = "generic profile"
    exec = ["notify-send shikane \"Profile $SHIKANE_PROFILE_NAME has been applied\""]
        [[profile.output]]
        search = "/DP-[1-9]"
        enable = true
        exec = ["swayws range --numeric 1 5 $SHIKANE_OUTPUT_NAME"]

        [[profile.output]]
        search = "n%HDMI-"
        enable = true
        mode = "preferred"
        exec = ["swayws range --numeric 6 10 $SHIKANE_OUTPUT_NAME"]

# AUTHORS

Hendrik Wolff

# SEE ALSO

shikane(1), shikanectl(1), swayws, TOML