opening the zellij configuration directory, generating the default config.kdl, understanding the keybinds, options, and plugins blocks, plus reloading without restart and saving preferences via session mode.

For seven episodes, you've pressed keys that were all configured by default. But you'll never become a truly productive Zellij user if you don't start writing configuration. Everyone has different hands, editors, and habits — and Zellij understands that. Almost every behavior you've learned so far — keybindings, scrollback size, mouse behavior, the plugins shown in the bars — comes from a single file: config.kdl. In this episode, that file becomes yours.
Why does configuration matter? Because Zellij is designed to fit your habits, not the other way around. Zellij's defaults are good, but not for everyone. Maybe you want a Ctrl+b tmux style, or a scrollback larger than 10000 lines, or you want to disable the mouse. All of those are decisions written once in config.kdl, stored in dotfiles, and carried everywhere — including to production servers. This is the beginning of a Zellij that's "yours".
This episode's map: first we find and understand the configuration directory structure. Then we generate the default file with zellij setup --dump-config. Next, the three core blocks: keybinds, options, and plugins. Finally, two operational skills: reloading configuration without restarting and saving preferences through Session mode. By the end of this episode, config.kdl will no longer feel like a mysterious file, but Zellij's control panel.
One principle ties it all together: configuration is code. config.kdl is plain text that can be committed to Git, reviewed, tested, and synced between machines. In episode 27 we'll wrap all of it into dotfiles that can be bootstrapped with one command. For now, start with one file and one directory — because a tidy foundation determines how far you can go.
Zellij looks for its configuration in a priority order: the file given via the --config flag, the ZELLIJ_CONFIG_FILE environment variable, then the default location. The default location follows each operating system's convention. On Linux (which follows the XDG standard) configuration lives in ~/.config/zellij/, and on macOS in the Application Support directory. Windows follows the equivalent %APPDATA% path.
~/.config/zellij/
├── config.kdl
├── layouts/
│ └── (.kdl layout files, covered in episode 10)
├── themes/
│ └── (.kdl theme files, covered in episode 11)Note two things. First, Zellij's configuration language is KDL — not YAML like the classic tmux config, not TOML. KDL looks like a cross between XML and a programming language: nodes are called by name, followed by keys and values. The structure is concise and easy to read. Second, the layouts/ and themes/ folders are Zellij's working directories: the .kdl files inside them will be covered in episode 10 (layouts) and episode 11 (themes). Custom WASM plugins, meanwhile, are loaded from any location you point to with a file:... URL — episode 15 will dissect that.
For those who want maximum flexibility, there's ZELLIJ_CONFIG_DIR to override the entire configuration directory. The combination of ZELLIJ_CONFIG_FILE and ZELLIJ_CONFIG_DIR lets you have several Zellij profiles and switch between them by context — one for local work, one for servers.
The three config discovery paths — the --config flag, the environment, and the default location — work in a strict priority order. The flag wins over everything, then ZELLIJ_CONFIG_FILE, then the default location. This is very practical for testing: zellij --config /tmp/experiment.kdl runs a session with a temporary config without touching your main one. Once the result is right, copy it to a permanent location and make it part of your dotfiles.
zellij setup --dump-configIn most cases, Zellij creates config.kdl automatically on the first session. But to start from a complete foundation — and to learn every option along with its comments — the best way is to generate the default file explicitly.
mkdir -p ~/.config/zellij
zellij setup --dump-config > ~/.config/zellij/config.kdlzellij setup --dump-config writes the entire default configuration to stdout — hundreds of lines, complete with explanatory comments on every option. Redirecting to config.kdl gives you a complete, ready-to-edit copy. Open it in your editor and gradually remove comments as you understand each section.
keybinds {
normal { ... }
resize { ... }
pane { ... }
}
options { ... }
plugins { ... }The dumped file is invaluable as living documentation. Every option is followed by a comment explaining its function, default value, and whether it requires a restart. Instead of memorizing the whole configuration API, keep this file and read the relevant section when needed. According to Zellij 0.44.x guidance, the most common configuration order is: keybinds, then options, then plugins.
Note
zellij setup --dump-config only prints to stdout — it doesn't change any file. It's safe to run anytime. To check environment health, there's zellij setup --check, which you already know from episode 0. These two setup commands are the bridge between installation and configuration.
keybinds Block: Controlling Every ModeThe keybinds block is the heart of Zellij's mode-based philosophy. Inside it, every mode is a sub-block, and every bind line connects one or more keys with one or more actions. The syntax:
keybinds clear-defaults=true {
normal {
bind "Ctrl p" { SwitchToMode "Pane"; }
bind "Alt n" { NewPane; }
bind "Alt h" "Alt Left" { MoveFocusOrTab "Left"; }
}
pane {
bind "x" { CloseFocus; SwitchToMode "Normal"; }
bind "f" { ToggleFocusFullscreen; SwitchToMode "Normal"; }
}
}Two key things here. clear-defaults=true replaces all default keybindings with only what you write — the best way to start from a clean slate. Without that flag, your bind lines add on top of the defaults. There's also unbind to remove specific keys, and unbind-all to empty a single mode. Each mode has its own context: pane, tab, resize, move, scroll, session, tmux, and locked.
The hidden power is in the multi-key and multi-action syntax. bind "Alt h" "Alt Left" binds two keys at once to the same action — no need for two lines. And one key can trigger several sequential actions, like CloseFocus then SwitchToMode "Normal", exactly like the default behavior when closing a pane. In episode 9 you'll dissect this block deeper, including handling conflicts between keybindings.
Because every mode has its own block, you can change one mode's behavior without touching the others. Change resize so the h key shrinks instead of enlarges? Just edit the resize block — other modes are untouched. And because Zellij shows keybinding hints in the status bar every time you enter a mode, you can test new keybinds without opening a manual. This edit-test cycle is very short, especially with the auto-reload covered at the end of this episode.
options Block: Setting Global BehaviorIf keybinds decides which keys, options decides how Zellij behaves. Here are the options you'll most often change at first:
| Option | Default value | Function |
|---|---|---|
mouse_mode | true | Enables mouse interaction (select, scroll, resize) |
scroll_buffer_size | 10000 | Number of lines stored per pane in the scrollback |
copy_command | (OSC 52) | Command for copying text to the clipboard |
copy_on_select | true | Auto-copy when a selection is released |
default_layout | default | Layout loaded when a session starts |
theme | default | Interface color theme |
pane_frames | true | Shows boundary frames between panes |
default_mode | normal | Mode active when Zellij starts |
options {
scroll_buffer_size 50000
copy_command "wl-copy"
mouse_mode true
pane_frames true
}Note the KDL syntax in this block: the option name followed by a value, without an equals sign or semicolon. scroll_buffer_size 50000 raises the scrollback memory from 10000 to 50000 lines per pane — useful for long logs, at the cost of more memory. copy_command "wl-copy" replaces the OSC 52 protocol with the Wayland command you already know from episode 6. pane_frames false hides frames permanently — an aesthetic decision that can also be done momentarily with Ctrl+p then z.
Two options most often cause surprises. mouse_mode false solves copy-paste conflicts in certain terminals (some terminals struggle to select text while mouse mode is active), but you lose drag-resize and mouse scroll. And scroll_buffer_size isn't a "the bigger the better" option without cost — every pane keeps its buffer in memory, so hundreds of thousands of lines times dozens of panes can add up. Start at 50000 and raise it only if needed.
Tip
The best way to learn the options block: open the dumped config.kdl, and read the options section while matching them against the behaviors you've experienced over the past seven episodes. mouse_mode, scroll_buffer_size, copy_command — all of these appeared in previous episodes. Changing them here means moving control from the session to permanence.
plugins Block: The Interface You See Every DayMany don't realize that the tab bar on top, the status bar at the bottom, and strider are plugins — WASM modules running inside Zellij. The plugins block determines which plugins are loaded and where. This is the part you see every second, even though you rarely touch it.
plugins {
tab-bar location="zellij:tab-bar"
status-bar location="zellij:status-bar"
strider location="zellij:strider"
compact-bar location="zellij:compact-bar"
}Four built-in plugins make up the interface: tab-bar (the tab list at the top), status-bar (the bottom bar with mode and hints), strider (file explorer, episode 14), and compact-bar (a compact version of the status bar). The zellij:... URLs are aliases for built-in plugins; you can replace location with file:/path/to/plugin.wasm or https://... for custom plugins — the foundation you'll build in episodes 15 and 16. There's also a load_plugins block for loading plugins in the background when a session starts.
Swapping built-in plugins is the most popular way to change Zellij's appearance without touching code. Want a leaner status bar? Point status-bar location at the compact-bar or a custom plugin. Want a tab bar with extra info? Replace tab-bar location with a community plugin. Because Zellij treats the interface as plugins, you get a level of customization traditional multiplexers don't have — and episode 15 will show you how to write your own plugin.
Important
Changes to the plugins block — especially replacing a plugin's location — generally require a session restart to take effect, unlike keybinds which activate immediately. The comments on options in config.kdl always mark this. Before tinkering with plugins, check whether the running session you're using can be restarted without losing work.
One of the most pleasant features since Zellij 0.41: configuration is reloaded automatically. Zellij installs a file-watcher on the active config.kdl. Change the file, save, and most changes apply directly to the running session — new keybindings activate within seconds, themes change before your eyes. No Ctrl+r, no restart, no detach-attach.
Auto-reload works through a file-watcher that monitors config.kdl every second. That means an editor with auto-save will trigger a reload even without an explicit save — and a file deleted temporarily will be waited for until it reappears. One small note: because the watcher works on the file directly, a symlinked config (for example from a dotfiles manager like stow) may not be detected on certain versions — copy the file physically if you hit this.
However, not every option can be reloaded this way. Options that affect architecture — for example default_mode, session_serialization, or layout_dir — are marked Requires restart in the config.kdl comments. For options like those, you must start a new session (or restart the old one). The correct habit: check the option's comment before expecting a change to apply instantly.
The second way to change preferences is through Session mode. Press Ctrl+o, then c to open the Configuration screen. Here you can change keybinding presets (including non-colliding modes), change the secondary modifier, and set options without touching a file. Changes can be applied to the running session or saved to config.kdl to persist — the difference is just one step on that screen. Meanwhile, Ctrl+o then w opens the session-manager for managing many sessions.
zellij action save-sessionZellij serializes sessions periodically for resurrection purposes. zellij action save-session triggers an immediate serialization — useful when you've just restructured a layout and want to make sure that state is stored before closing the session. Resurrection details will be covered in episode 17; for now, remember your preferences have a saving path: the config file for permanence, Session mode for interactivity.
Tip
The most effective experimentation workflow: run Zellij, open config.kdl in an editor in one pane, then change a value and save — watch the change apply instantly in another pane. When satisfied, commit the config to dotfiles. This is the fastest feedback loop Zellij offers, and it's the reason customizing Zellij feels so addictive.
key: value and YAML-style indentation don't apply. The KDL syntax is node key=value without colons. Mixing the two makes the parser fail — learn KDL's shape once, and it's done.clear-defaults=true. Without this flag, your custom keybinds only add to the defaults — and hidden conflicts can make keys behave unexpectedly. If you want full control, start with keybinds clear-defaults=true.copy_command for the wrong platform. A config containing pbcopy on Linux won't work. Keep config.kdl portable by matching the clipboard command per machine, or keep separate profiles via ZELLIJ_CONFIG_FILE.Ctrl+o then c without touching a file. This is the fastest way to test keybinding presets before deciding to write them permanently.You now hold Zellij's key: you know where the config lives, how to generate the default version, and how to read and write its three main blocks. keybinds controls the keys, options controls behavior, plugins controls the interface. Combined with restart-free reloading and preference saving through Session mode, you no longer depend on factory settings — Zellij starts adapting to you, not the other way around.
Key takeaways:
~/.config/zellij/config.kdl, in the KDL language.zellij setup --dump-config > config.kdl.keybinds, options, plugins.Ctrl+o then c) for interactive configuration; save-session for immediate serialization.In episode 9 next, we dive deeper into the keybinds block: custom keybindings and keybinding conflicts. You'll learn the per-mode bind/unbind syntax, clear-defaults and unbind-all, multi-actions in a single keybind, and strategies for resolving conflicts between Zellij, your shell, and your editor. See you in episode 9.