tidying up the core config.kdl options: mouse_mode, scroll_buffer_size, copy_command, default_mode, default_layout, and session_serialization, plus per-pane environment and working directory management.

Welcome to episode 12 of the Learn Zellij series! The previous three episodes shaped the way you operate Zellij — keybindings in episode 9, layouts in episode 10, and appearance in episode 11. Now we align the application's core behavior: Options & Environment Management. This is the episode about the options that are often forgotten because they work behind the scenes, even though they determine how Zellij responds to the mouse, stores scrollback, copies text, starts sessions, and survives between reboots.
There are three areas you'll master: (1) the core options at the root of config.kdl — mouse_mode, scroll_buffer_size, copy_command, default_mode, default_layout, theme, and session_serialization, (2) session serialization and resurrection so workspaces can be reborn after a crash or reboot, and (3) environment and working directory management — per pane, per session, and how all of it survives when a session is resurrected.
Why does this episode matter? Most of Zellij's "magical" experience is actually just correctly configured options. A scrollback that never runs out, copying that lands directly in the system clipboard, sessions that reappear after a crash — none of that is magic, it's options you understand. This episode closes the configuration phase of the series, and the next episode opens the automation era with pipes and CLI actions.
One thing to understand from the start: not all options work the same way. Some options apply immediately when config.kdl is reloaded — Zellij continuously monitors this file — while others only apply after a session is restarted. Options that demand a restart are usually related to server structure or buffers already allocated at startup. A healthy habit: after changing an option, check whether the change is felt immediately; if not, restart the session and compare. Throughout this episode, options requiring a restart are always marked. Let's begin.
A fact that often surprises users coming from older versions: in Zellij 0.44, options are written directly at the root of config.kdl, without being wrapped in an options node. The file structure consists only of global nodes (keybinds, themes, plugins, env, and a few others) plus top-level option lines. Following this pattern keeps the config flat and easy to read.
mouse_mode true
scroll_buffer_size 10000
copy_on_select true
default_mode "normal"
default_layout "default"
theme "dracula"Each line above is an option: one key, one value. Some options apply immediately when the config reloads (the config is watched live), others demand a session restart — always check the comments in the zellij setup --dump-config output to know which. Below we dissect the options you'll most often need one by one.
Note
Don't write an options block in config.kdl — Zellij doesn't recognize that node and the lines inside it will be ignored. All options live at the root of the file, alongside keybinds and themes. This is one of the biggest differences between the modern KDL config and Zellij's first-generation YAML config.
These three groups of options determine how you interact with panes physically: the mouse for clicks and selection, scrollback for screen memory, and the clipboard for text transfer.
mouse_mode true
scroll_buffer_size 10000
copy_on_select truemouse_mode enables mouse support — selecting text, scrolling, resizing panes by dragging edges, and hover for visual effects. scroll_buffer_size is the maximum number of lines Zellij stores for each pane in the scrollback buffer; excess lines are discarded FIFO. The value 10000 is a reasonable default, but for workloads like tail -f with giant output, you can raise or lower it according to your memory needs. The copy_on_select option makes selected text auto-copy while also clearing the selection when the mouse button is released.
For the clipboard, Zellij uses OSC 52 by default when the terminal supports it. If your terminal doesn't support it, copy_command provides a bridge to the system clipboard through an external command — text is piped to that command's stdin. Correct examples differ per platform:
copy_command "xclip -selection clipboard"| Option | Common Value | Function |
|---|---|---|
mouse_mode | true / false | Enable mouse support |
scroll_buffer_size | 10000 | Scrollback lines per pane (FIFO) |
copy_on_select | true / false | Auto-copy when a selection is released |
copy_clipboard | "system" / "primary" | Clipboard destination (doesn't apply to copy_command) |
copy_command | "pbcopy" etc. | External command for copying |
Besides copy_command, the copy_clipboard option sets the copy destination when Zellij uses OSC 52: "system" for the system clipboard, or "primary" for the primary selection buffer common on X11/Wayland. This value doesn't apply when copy_command is used, because the text is already piped to that external command. To edit scrollback content directly in an editor, the scrollback_editor option sets the editor used by the e action in Scroll mode — it defaults to following $EDITOR or $VISUAL, but you can force a specific path for consistency across machines.
The following three options determine each session's starting conditions: which mode Zellij starts in, which layout loads, and which theme is used.
default_mode "normal"
default_layout "compact"
theme "dracula"default_mode sets the input mode when a session starts — "normal" for the standard experience, or "locked" for the unlock-first pattern we discussed in episode 9. default_layout points to the layout loaded at startup; its value is a file name in ~/.config/zellij/layouts/ or a full path. theme picks a theme from the built-in themes or the themes directory. All three closely connect to episodes 9, 10, and 11 — now you understand how those options link into a single whole.
The relationship between default_mode and the keybinding preset is worth underlining. Since 0.41, Zellij forwards unbound keys verbatim to applications inside panes when the active mode is locked or default_mode. That means choosing default_mode "locked" isn't just changing the starting mode — it changes how Zellij treats all input: you must unlock the interface with Ctrl+g before switching modes, exactly like the Unlock-First preset. Conversely, default_mode "normal" lets keys flow straight to the shell while all mode prefixes stay active. Choose according to your tolerance for keybinding conflicts.
One of Zellij's most appreciated advantages is session resurrection: every session is periodically serialized to the cache directory, so even after an intentional quit or a crash, the workspace can be reborn. This mechanism is controlled by the following options.
session_serialization true
pane_viewport_serialization true
scrollback_lines_to_serialize 20000
serialization_interval 1session_serialization turns serialization on or off. When active (the default), Zellij saves the session layout — tabs, panes, cwd, and running commands in each pane — to a layout file that can be reloaded like a regular layout. pane_viewport_serialization adds the pane viewport to the serialization, and scrollback_lines_to_serialize limits how many scrollback lines are stored; a value of 0 means all. serialization_interval sets the pause between saves in seconds — one second by default. The serialization result can be read, edited, even shared as a layout between machines.
The serialized file is stored as a KDL layout in Zellij's cache directory — on Linux usually ~/.cache/zellij/. Because its format is identical to a regular layout, you can open, edit, or load it manually with zellij --layout <file> at any time, even on another machine. For workloads that don't want to store any state, turn serialization off entirely; conversely, if you want a complete archive including pane screen contents, enable pane_viewport_serialization and set scrollback_lines_to_serialize to an adequate number. Remember that serialization adds cache and disk load, so tune it to your machine's needs.
Tip
Because sessions are serialized as human-readable KDL layouts, you can open a serialized file to learn how your layout looks from Zellij's perspective — or make it the starting point of a custom layout. This is one of the best ways to transition from the manual workspaces of episode 10 toward the automatically stored workspaces of episode 17.
Keep in mind: serialization doesn't explicitly store environments. When a session is resurrected, Zellij re-runs command panes with the environment coming from the config and layout — not from variable values you changed at runtime. This is the bridge to the last part of this episode.
Zellij gives you three layers for managing environments. The first layer is the env block in config.kdl — a key-value map injected into every terminal pane Zellij starts.
env {
APP_ENV "production"
LOG_LEVEL "debug"
RUST_BACKTRACE 1
}The second layer is the env_vars node inside a pane in a layout — an environment specific to that pane, like we wrote in episode 10. The third layer is the working directory: cwd on a layout, tab, or pane sets the working directory, and Zellij also provides the default_cwd option for all new panes.
layout {
pane cwd="/home/arman/dev/belajar-zellij" split_direction="vertical" {
pane focus=true
pane {
command "node"
args "-r" "dotenv/config" "index.js"
env_vars {
PORT "4000"
}
}
}
}Besides the environments you define, Zellij injects its own integration variables: ZELLIJ is set to 0 inside a session, and ZELLIJ_SESSION_NAME carries the active session name — useful for scripts and prompts that want to be context-aware. On persistence: because environments from env and env_vars are re-resolved every time Zellij starts a pane, defining variables in the config and layout means that environment survives every resurrection. Conversely, variables you export manually inside a shell only live for that shell, and are lost when the session is resurrected. The rule of thumb is simple: environments that must be consistent across sessions live in the config/layout, not at runtime.
There are two more integration variables worth knowing: ZELLIJ_AUTO_ATTACH makes Zellij immediately attach to an existing session instead of creating a new one, and ZELLIJ_AUTO_EXIT makes the shell exit when Zellij closes — a convenient pair for terminal emulators you treat as permanent "Zellij windows". Both are read from the shell environment before Zellij runs, not from inside the session. Finally, two options round out this area: default_shell replaces the shell used for terminal panes — useful if your login shell feels slow due to a heavy rc file — and the pane_frames node controls pane frame decorations like rounded corners (rounded_corners) and hiding the session name (hide_session_name).
Important
When a session is resurrected, command panes re-run with the environment from the config and layout, but not from the runtime values you last saw. If a command needs a token or variable generated at runtime, don't put it in a manual export — wrap it in the command pane's args or store it in the layout's env_vars so resurrect behavior is predictable.
options block. Zellij 0.44 doesn't recognize that node and silently ignores its lines. Fix: write all options at the root of config.kdl, alongside keybinds and themes.scroll_buffer_size. A giant value across many panes means bloated memory. Fix: start from the 10000 default, adjust only if the workflow truly needs long buffers.copy_command for the platform. pbcopy doesn't exist on Linux, xclip doesn't exist on Wayland. Fix: choose per environment — xclip -selection clipboard for X11, wl-copy for Wayland, pbcopy for macOS.default_layout and session_serialization only apply after a session restarts. Fix: check the "(Requires restart)" notes on the dumped config.export are lost when a session is resurrected. Fix: define important environments in the env config block or env_vars layout nodes so they're consistent across sessions.Warning
session_serialization writes session state — including running commands and cwd — to the cache directory on disk. On shared machines or sensitive environments, make sure you're aware that this state is stored and can be resurrected; if unwanted, turn it off with session_serialization false. Session and data security will be discussed in more depth in episode 22.
In this episode 12 you've aligned Zellij's core behavior: the options at the root of config.kdl — mouse_mode, scroll_buffer_size, copy_command, default_mode, default_layout, and theme — session serialization with session_serialization, pane_viewport_serialization, and scrollback_lines_to_serialize, and three-layer environment management via the config env, layout env_vars, and working directories. This closes the configuration phase of the series: keybindings, layouts, appearance, and behavior are now entirely yours.
Key takeaways:
options block.session_serialization lets workspaces be reborn after a crash.env and layout env_vars.Phase 3 of the Learn Zellij series — configuration, layouts, appearance, and options — is complete. In episode 13 next, we enter a new era: automation. Pipes, CLI Actions, and Automation will turn Zellij from a workspace you operate into a workspace you can script — sending non-interactive commands, streaming data between panes, and building workflows runnable from a task runner. See you in episode 13!