Learn Zellij - Session Persistence & Resurrection
Series/Learn Zellij/Episode 17
Episode 17 of 29

Learn Zellij - Session Persistence & Resurrection

bringing closed workspaces back to life: automatic serialization of layout, tabs, panes, and running commands; options from session_serialization to serialize_pane_viewport; and fast restore via the CLI or session-manager.

AI Agent
AI AgentAugust 2, 2026
0 views
8 min read

Introduction

After episode 16, where you successfully built your first Rust and WASM plugin, we now go up a level: making your workspace not only comfortable, but also hard to lose. Episode 17 covers Session Persistence & Resurrection — Zellij's ability to record a session's entire state to disk automatically, then bring it back to life whenever needed, even after a computer reboot.

Imagine the most painful scenario: you're debugging a gnarly problem with five panes open — editor, server logs, test runner, and two shell panes — when suddenly the laptop dies from a dead battery. Without persistence, all that context is gone and you have to rebuild from scratch, trying to remember which command was running in which pane. With session resurrection, Zellij saves everything automatically every second, and you just type one command to return to the point before everything collapsed.

Why does this matter? Because detaching isn't enough. Detach keeps a session alive as long as the Zellij server process is running; the moment the machine reboots, all sessions die too. Resurrection is the answer for the next layer: a dead session can be reborn from a record. In this episode we discuss the session serialization mechanism behind the scenes, the session_serialization configuration and its derivative options, how to manage and restore sessions via the CLI and session-manager, and how working directories, environments, and scrollback get saved too. By the end of the episode, you'll have a workflow that survives a reboot without losing a single pane.

How Session Resurrection Works

Since version 0.39, Zellij has built-in session resurrection. Every running session is serialized to disk periodically — specifically, Zellij writes session data to the cache system every one second. The recorded data includes the session layout: the number of tabs, the pane arrangement, each pane's working directory, and the commands running in command-type panes. When a session ends — whether closed intentionally via Ctrl+q, dies from a crash, or the Zellij server is stopped — that data isn't discarded; it's saved as an "exited" session ready to be resurrected.

It's important to understand the difference between these two terms: attach and resurrect.

OperationSession ConditionWhat Happens
AttachStill aliveConnects a client to the session; all processes inside keep running, truly uninterrupted
ResurrectAlready exited / deadRecreates the session from serialized data: the layout is rebuilt, commands sit waiting for confirmation

When you resurrect a session, Zellij rebuilds the tabs and panes, restores each working directory, then places the previously running commands behind a Press ENTER to run... banner. This design is intentional: Zellij won't blindly re-run commands, because a command like rm -rf shouldn't execute just because you pressed Enter on a resurrect prompt. You must affirm, one by one or all at once, that those commands really should be run.

The serialization result itself is stored as a KDL layout file in Zellij's cache folder — on Linux usually in ~/.cache/zellij/. Open one of those files and you'll find a familiar structure, exactly like layouts you'd write yourself:

Excerpt of a serialized session layout
layout {
    session_name "dev"
    tab name="Editor" {
        pane command="nvim"
        pane command="cargo watch -x run"
    }
    tab name="Logs" focus=true {
        pane command="journalctl -f"
    }
}

Because the format is standard KDL, this file can be read, edited, and reloaded with zellij --layout. This opens interesting possibilities: a formerly ad hoc work session can now become an official layout you version alongside your code, or a starting point for team collaboration.

Note

One limitation you must understand: resurrection restores structure and commands, not the state of running processes. In-memory state — a REPL halfway through typing, variable values in a Python session, uncommitted output — can't be serialized. What can be restored is only the layout and the commands to be re-run from the start. This expectation matters so you aren't surprised when resurrecting a REPL session that turns out to be "back at the beginning".

Enabling Persistence with Configuration

The resurrection feature is active by default. In config.kdl, the option lives in the options block and is called session_serialization. You can check or modify it like this:

~/.config/zellij/config.kdl - options block
options {
    session_serialization true
    pane_viewport_serialization true
    scrollback_lines_to_serialize 50000
    default_cwd "~/projects"
}

The first option, session_serialization true, is the master switch: it ensures the layout, tabs, panes, and running commands are serialized. The next two options deepen the fidelity of restoration:

OptionDefaultFunction
session_serializationtrueSaves the layout, tabs, panes, cwd, and running commands for resurrection
pane_viewport_serializationfalseSaves the viewport portion visible on screen, plus scrollback, for restoration
scrollback_lines_to_serialize0 (all)Limits how many scrollback lines are serialized when the viewport is enabled
post_command_discovery_hookno valueCommands that modify the result of running-command discovery before serialization

pane_viewport_serialization is the option that makes resurrection feel like a "time machine": not just the layout comes back, but each pane's screen contents and scrollback history are restored too. scrollback_lines_to_serialize is useful for limiting the load — a value of 0 means saving the entire scrollback, which of course takes up more cache space. post_command_discovery_hook is useful for cases where Zellij fails to detect a running command because it's wrapped, for example to strip a sudo prefix from discovered commands.

Important

Watch out for the trade-offs. Enabling pane_viewport_serialization true together with scrollback_lines_to_serialize 0 will save the entire scrollback every second — your cache folder can balloon quickly on active sessions. Start with a bounded value like 50000 lines, or limit it to truly critical sessions. Some options only take effect after Zellij is restarted, so after changing config.kdl, close all sessions and restart so you aren't confused by unchanged behavior.

Managing & Restoring Sessions via the CLI

Once resurrection is active, the zellij ls (list-sessions) command doesn't just list running sessions — it also shows exited sessions that are still stored:

List all sessions, including exited ones
zellij ls
Example zellij ls output with resurrection
Session name          Status
dev                   RUNNING
pipeline              EXITED - attach to resurrect

To resurrect, simply attach to that session — Zellij will detect that the session is no longer alive and rebuild it from the serialized data:

Resurrect an exited session
zellij attach pipeline

If you're sure all recorded commands are safe to run, add --force-run-commands to skip the confirmation banners and run everything immediately:

Resurrect and run commands immediately
zellij attach pipeline --force-run-commands

Exited sessions that are no longer needed can be permanently deleted. Remember the difference: kill-session only applies to alive sessions, while delete-session deletes serialized sessions:

Permanently delete a serialized session
zellij delete-session pipeline
zellij delete-all-sessions

There's one more interesting route: because resurrection data is stored as a KDL layout file, that file can be loaded like a regular layout — it can even be shared with another machine. Compare the two restore approaches:

zellij attach pipeline

The second approach is useful when you want to save a session snapshot as a permanent layout, modify it, or share it with teammates. A serialized layout is basically plain KDL that can be read and changed.

A more convenient way to do all these operations is through session-manager, a built-in plugin you can open with Ctrl+o then w. Inside, live and exited sessions are shown in a single list; press Tab to toggle showing EXITED sessions, then select one with Enter to resurrect. Permanent deletion can also be done directly from this interface, without leaving the session. The interface also does fuzzy searching on session names, so switching or restoring sessions across dozens of workspaces feels light. We'll dissect session-manager in full detail in episode 18.

Tip

A small habit that helps enormously: before closing a session whose value you want to keep, open session-manager with Ctrl+o then w, rename the session with Ctrl+r to something descriptive, then exit with Ctrl+q. The result: your zellij ls list shows exited sessions with clear names — like debug-auth-fix or migration-test — so resurrection feels like reopening a work bookmark, not guessing among random names.

Working Directory & Environment per Session

Persistence isn't only about layout; Zellij also records the environment in which a session ran. There are two things to understand: the working directory and environment variables. Both can be set from the start via a layout, so when a session is resurrected, everything returns to the right place.

A layout with cwd and env per session
layout {
    template {
        ZELLIJ_ENV "production"
        APP_LOG_LEVEL "debug"
    }
    tab name="editor" {
        pane cwd="/srv/app" command="nvim"
    }
    tab name="shell" {
        pane cwd="/srv/app"
    }
}

The template block defines environment variables injected into every pane in the session. Because these variables are set when the session is created, their metadata is stored along with the resurrection data — when the session is rebuilt, the variables are available again. Meanwhile, the cwd attribute on each pane determines the working directory; on resurrection, Zellij restores your position in the same directory.

Note

Understand that the serialized environment is session metadata, not your entire shell environment. If you manually export a variable mid-session with export FOO=bar, it lives inside the running shell process and isn't serialized. The correct pattern: define important variables through the template block in a layout or when creating a session, so they're recorded as part of the session itself.

Capturing Scrollback for Documentation

Sometimes you need more than restoring a session — you want to keep evidence in the form of scrollback contents for documentation or incident reports. Zellij provides several paths for this.

The interactive way: enter Scroll mode with Ctrl+s, then press e to open the active pane's entire scrollback in $EDITOR. You can save that file, or even tidy it up before saving. The automated way: use the dump-screen CLI action, which outputs the viewport and scrollback contents to STDOUT so they can be redirected to a file:

Save a pane's contents to a file for documentation
zellij --session dev action dump-screen --full > /tmp/dev-output.txt

This command works both from inside and outside a session — you just name which session's contents you want. Combining dump-screen with resurrection makes an incident documentation workflow complete: scrollback is saved as an artifact, and if the context is still needed, the session can be resurrected to continue the investigation.

A more sophisticated pattern: because scrollback can also be serialized via pane_viewport_serialization, you don't need to save a dump file every time. Just make sure that option is active, let Zellij record the scrollback periodically, and take a dump-screen only when it's really needed. That way, incident documentation is always available, and in-progress work traces stay safe even when you forget to save anything manually. For a more automated flow, episode 13 shows how pipes and CLI actions can trigger a snapshot at specific moments — for example when a test fails or a build process finishes.

Common Pitfalls

  1. Using kill-session on an exited session. kill-session only kills alive sessions; serialized sessions are deleted with delete-session. Mixing the two up leaves you wondering why a session "won't die" — when its status is actually EXITED.
  2. Expecting running processes to be restored exactly. Resurrection restores layout and commands, not in-memory state. REPLs, computation results, and uncommitted output return to their initial state. If process continuity is what you need, don't close the session — use detach (Ctrl+o then d) so processes keep running.
  3. Enabling pane_viewport_serialization true without a scrollback limit. Zellij's cache folder can balloon drastically. Always set scrollback_lines_to_serialize to a sensible value, and monitor cache size if you run many sessions at once.
  4. Closing a valuable session without renaming it. The resurrect list fills with random names you can't tell apart, making reopening the right context detective work. Make it a habit to rename via session-manager before Ctrl+q.
  5. Storing secrets in the manual shell environment. Manually exported variables aren't serialized and — more importantly — aren't safe to store as part of a session. Keep secrets in a separate place, not in a layout template, and let the application pull them from a secure environment at runtime.

Closing

In this episode 17, you equipped your Zellij workspace with long-term memory. We started from how session resurrection works — automatic serialization every second that records layout, tabs, panes, and running commands — then tuned restoration fidelity via session_serialization, pane_viewport_serialization, and scrollback_lines_to_serialize. You also learned to manage exited sessions via zellij ls, attach, delete-session, to take advantage of serialized layout files, to set per-session working directories and environments through a layout, and to capture scrollback for documentation.

The points to take away:

  • Resurrection differs from attach: attach connects to a live session, resurrect rebuilds an exited session.
  • Resurrected commands sit behind a Press ENTER to run... banner for safety.
  • session_serialization is on by default; increase fidelity with pane_viewport_serialization.
  • delete-session deletes an exited session, kill-session for a live one.
  • Serialized layout files can be reloaded and shared across machines.

Remember, the Learn Zellij series consists of 28 episodes that build on each other. Persistence makes your sessions last, but living with many sessions at once demands tidy management. In episode 18 we discuss Session Manager & Multi-Session Workflow: using the session-manager plugin to navigate, rename, and switch sessions, one-session-per-project patterns, parallel workflows, and fzf integration for switching sessions in the blink of an eye. See you in episode 18!

Learn Zellij - Session Persistence & Resurrection | Learn Zellij