| name | zellij-cli |
| description | Zellij terminal workspace orchestration for AI agents. Covers the mental model, targeting strategy, screen I/O patterns, safety boundaries, and composition workflows. Use `zellij <command> --help` for exact syntax; this skill teaches *when* and *why* to use each capability. |
zellij CLI Orchestration
This skill teaches you how to think about zellij, not how to type commands. For exact syntax, run zellij <command> --help or zellij action <command> --help. The CLI is self-documenting; this skill fills the gaps that --help cannot.
Quick Workflows
These show patterns, not syntax. Adapt flags via --help.
Discover → Target → Act
panes=$(zellij action list-panes --json --all)
zellij action dump-screen --pane-id terminal_4 --full
zellij action write-chars --pane-id terminal_4 "restart"
zellij action send-keys --pane-id terminal_4 Enter
zellij action dump-screen --pane-id terminal_4
Set up a workspace
zellij action new-tab --name build
zellij action new-pane --direction right
zellij run --name tests -- cargo nextest run --run-ignored all
Monitor and react
zellij subscribe --pane-id terminal_2 --format json --scrollback 200
zellij action dump-screen --pane-id terminal_2 --full --path /tmp/snap.txt
Session housekeeping
zellij -s dev action list-tabs --json --all
zellij action dump-layout > /tmp/layout-backup.kdl
zellij action dump-screen --pane-id terminal_1 --full --path /tmp/pane-backup.txt
Mental Model
Zellij has a strict containment hierarchy:
Session (top-level workspace, named or auto-named)
└─ Tab (workspace unit within a session, has a layout)
└─ Pane (terminal or plugin container, tiled or floating)
- Session: the outermost boundary. You can have many sessions. Only one is "current" per terminal. Managed with top-level commands (
list-sessions, attach, kill-session, delete-session).
- Tab: the main workspace unit. Each tab has its own pane layout. Tabs live inside a session.
- Pane: where work happens. Panes hold terminal processes or WASM plugins. Every pane has an ID in the format
terminal_N or plugin_N. Bare integers are treated as terminal panes.
- Floating pane: a pane detached from the tiled layout, overlaying it. Useful for transient tools.
Targeting Strategy
Never guess which pane or session you're acting on. Follow this priority:
-
Environment variables (most reliable when inside zellij):
ZELLIJ_SESSION_NAME — current session name
ZELLIJ_PANE_ID — current pane ID (terminal_N or plugin_N)
ZELLIJ — set to "0" when running inside zellij
-
Discovery (when env vars are absent or you need other panes):
zellij action list-panes --json --all — all panes with geometry, state, command, tab info
zellij action list-tabs --json --all — all tabs with dimensions, pane counts, layout info
zellij action current-tab-info --json — focused tab only
zellij list-sessions — all sessions with status
-
Explicit IDs (always prefer over "focused pane" assumptions):
- Most
action commands accept --pane-id <ID> or --tab-id <ID>
- Session targeting from outside:
zellij -s <session_name> action ...
Key principle: discover first, then act with explicit IDs. Never assume the focused pane is the right target — the user may be looking at a different tab or the agent may be running in a different context.
Discovery Before Action
Before any mutating operation, inspect the current state:
- Run
list-panes --json --all to understand the workspace topology
- Identify the target pane by its
terminal_command, title, plugin_url, or tab_name fields
- Use the
id field (with terminal_ or plugin_ prefix) for all subsequent targeting
- Check
is_floating, is_suppressed, is_focused to understand pane state
The JSON output from list-panes and list-tabs includes rich metadata: geometry (pane_x, pane_y, pane_rows, pane_columns), state (is_focused, is_fullscreen, is_floating, exited, exit_status), and identity (terminal_command, plugin_url, tab_id, tab_name).
Reading Screen Content
Two primitives, different use cases:
| Need | Primitive | Key insight |
|---|
| Point-in-time snapshot | zellij action dump-screen | Returns viewport; add --full for scrollback, --ansi to preserve styling. Use --pane-id to target. |
| Continuous updates | zellij subscribe | Streams render updates. Use --format json for structured parsing. Accepts multiple --pane-id values. |
When to use which:
- dump-screen: parsing command output, checking if a build finished, reading error messages, creating checkpoints before destructive operations
- subscribe: watching a long-running process, reacting to output changes in real-time, monitoring multiple panes simultaneously
Parsing tip: use --ansi only when you need color/styling information (e.g., distinguishing error output). Plain text output is easier to parse and smaller.
Writing Input
Four primitives, each for a different situation:
| Primitive | Use when | Example scenario |
|---|
write-chars | Typing literal text into a shell or program | Entering a command like cargo test |
send-keys | Sending keyboard shortcuts, control sequences, or special keys | Enter, Ctrl c, Alt Shift b, F1, arrow keys |
paste | Sending multiline text safely (uses bracketed paste mode) | Pasting a code block or multi-line script |
write | Sending raw bytes when a program expects exact byte sequences | Sending ANSI escape codes directly |
Decision tree:
- Is it a keyboard shortcut or special key? →
send-keys
- Is it multiline text? →
paste
- Is it raw bytes or escape sequences? →
write
- Everything else →
write-chars
Important: after write-chars, you usually need send-keys Enter to execute the command. write-chars types the text but does not press Enter.
Safety Boundaries
- Never close panes, tabs, or sessions unless the user explicitly asks. These are destructive and may kill running processes.
- Checkpoint before destructive operations: run
dump-screen --full on affected panes before closing, killing, or overriding layouts.
- Prefer explicit IDs over focused-pane assumptions. The agent may not share focus context with the user.
- Don't create excessive panes or tabs. Check existing topology first; reuse panes when possible.
- Don't send input to the wrong pane. Always verify pane ID before
write-chars or send-keys.
- Use
--json output whenever another tool or the agent will parse results. Human-readable output is fragile to parse.
Composition Patterns
Read-Decide-Act Loop
The fundamental pattern for autonomous terminal work:
- Read:
dump-screen --pane-id <ID> --full to see current state
- Parse: extract the relevant information (build status, error messages, prompts)
- Decide: determine the next action based on what you read
- Act:
write-chars / send-keys to the target pane
- Verify:
dump-screen again to confirm the action had the expected effect
Workspace Setup
When setting up a multi-pane workspace:
- Inspect existing tabs with
list-tabs --json
- Create a new tab if needed with
new-tab (optionally with --layout)
- Create panes with
new-pane (use --direction for tiled, --floating for overlays)
- Run commands in panes using top-level
zellij run (returns pane ID) or write-chars + send-keys Enter
Plugin IPC
When communicating with zellij plugins:
- Use
launch-or-focus-plugin (idempotent) over launch-plugin (creates duplicates)
- Send structured payloads via
pipe with --name as the channel and --plugin for targeting
- Use
start-or-reload-plugin during development when plugin source changes
Scripting & Batching
Batch multiple zellij calls into one shell invocation when the sequence is predetermined. Fewer round-trips, atomic workspace mutations.
Batch when: workspace setup, bulk pane input, teardown, read-then-act with known logic.
Don't batch when: each step needs the previous output parsed for a decision, error recovery branches, or the user must decide between steps.
Three shapes:
| Shape | When | Example |
|---|
Inline chain (&& / ;) | 2–4 ordered commands, no variables or loops | new-tab && new-pane && run |
Temp script (/tmp/*.sh) | Variables, loops, conditionals; clean up with trap 'rm -f ...' EXIT | Complex workspace scaffolding |
| Pipeline / subshell | Discovery feeds directly into action via $(...) or pipes | Dynamic pane targeting with jq |
zellij action new-tab --name build && \
zellij action new-pane --direction right && \
zellij run --name server -- cargo run && \
zellij run --name tests -- cargo nextest run
pane_id=$(zellij action list-panes --json --all \
| jq -r '.[] | select(.tab_name=="build" and .title=="tests") | .id')
zellij action dump-screen --pane-id "$pane_id" --full
Self-Help Pattern
When you need exact syntax for any command:
zellij --help
zellij action --help
zellij action <command> --help
zellij <top-command> --help
This is always authoritative. Prefer it over memorized syntax.
Capability Map
Use zellij action --help for the full list. The major capability groups are:
| Capability | Top-level commands | Action commands |
|---|
| Sessions | list-sessions, attach, kill-session, delete-session | switch-session, rename-session, detach, save-session, list-clients |
| Tabs | — | new-tab, close-tab, close-tab-by-id, go-to-tab, go-to-tab-name, go-to-tab-by-id, go-to-next-tab, go-to-previous-tab, rename-tab, rename-tab-by-id, undo-rename-tab, move-tab, list-tabs, current-tab-info, query-tab-names, toggle-active-sync-tab |
| Panes | run, edit | new-pane, close-pane, focus-pane-id, focus-next-pane, focus-previous-pane, move-focus, move-focus-or-tab, move-pane, move-pane-backwards, resize, rename-pane, undo-rename-pane, list-panes, toggle-fullscreen, stack-panes, clear |
| Pane appearance | — | set-pane-borderless, toggle-pane-borderless, set-pane-color, toggle-pane-frames, toggle-pane-pinned |
| Screen I/O | subscribe | dump-screen, write-chars, send-keys, write, paste |
| Floating | — | toggle-floating-panes, show-floating-panes, hide-floating-panes, are-floating-panes-visible, toggle-pane-embed-or-floating, change-floating-pane-coordinates |
| Layouts | --layout, --layout-string | dump-layout, override-layout, next-swap-layout, previous-swap-layout |
| Plugins | plugin, pipe, list-aliases | launch-plugin, launch-or-focus-plugin, start-or-reload-plugin, pipe |
| Scrolling | — | scroll-up, scroll-down, scroll-to-top, scroll-to-bottom, page-scroll-up, page-scroll-down, half-page-scroll-up, half-page-scroll-down, edit-scrollback |
| Theme/Mode | — | set-dark-theme, set-light-theme, toggle-theme, switch-mode |
Deep-Dive References
Rules
- Discover before acting. Run
list-panes --json --all or list-tabs --json before mutating.
- Target explicitly. Use
--pane-id, --tab-id, or -s <session> instead of relying on focus.
- Use env vars first. Check
ZELLIJ_SESSION_NAME and ZELLIJ_PANE_ID before discovery.
- Don't destroy without asking. Never close panes, tabs, or sessions unless the user explicitly requests it.
- Checkpoint before destruction.
dump-screen --full before any close/kill/override.
- Use
--json for machine consumption. Parse structured output, not human-readable text.
- Batch when it helps. Use inline sequences, temp scripts, or pipelines when multiple zellij calls form a single logical operation — it reduces round-trips and keeps mutations atomic.
- Use
--help for syntax. This skill teaches strategy; the CLI teaches syntax.