Zellij layouts for Claude Code projects, Docker, pentesting, malware analysis, and OSINT β launch a full workspace with one command
Zellij is a terminal multiplexer (like tmux/screen) with a layout system that lets you define pane arrangements in .kdl files. This repo provides ready-to-use layouts you can launch with a single command.
git clone <this-repo> ~/zellij-conf
cd ~/zellij-conf
make setup # one-time: create working directories
make install # validate and install all layoutsThen launch any layout:
zellij --layout project options --default-cwd ~/projects/my-appA Zellij layout is a .kdl file that describes:
- Tabs β named workspaces you switch between (
Ctrl+t) - Panes β terminal splits within a tab (vertical/horizontal)
- Commands β auto-run commands in specific panes (e.g.
watch git status)
Layouts live in ~/.config/zellij/layouts/. Zellij finds them by name:
zellij --layout <name> # loads ~/.config/zellij/layouts/<name>.kdlOfficial docs: zellij.dev/documentation/layouts
zp # alias (named session: "claude")Multiple project tabs generated from generate-layout.sh, each with:
- 70% left β main shell (focused)
- 30% right β live
git status(top) + log tail or shell (bottom)
Plus fixed tabs: π cockpit (btop + ccusage) and π§ͺ scratch.
zo ~/projects/my-app # alias
zp-new my-app # creates dir + named session "my-app"Same pane pattern as above, without the cockpit. Use --default-cwd to point it at any directory.
zdk # alias (session: "docker", cwd: ~/docker)
zdk-new my-stack # creates ~/docker/my-stack, session "dk-my-stack"| Tab | Panes |
|---|---|
π³ stack |
Compose commands + live docker ps + image shell |
π logs |
docker compose logs -f + docker stats |
π§ debug |
Container exec + build shell |
zpt # alias (session: "pentest", cwd: ~/ops/pentest)
zpt-new acme-corp # creates ~/ops/pentest/acme-corp, session "pt-acme-corp"| Tab | Panes |
|---|---|
π― recon |
Scanner + enum + network monitor + notes |
βοΈ exploit |
MSF + payload + listener + proxy |
π post |
Session + pivot + process monitor + loot |
π loot |
Hash cracking + report |
zma # alias (session: "malware", cwd: ~/ops/malware)
zma-new emotet # creates ~/ops/malware/emotet, session "ma-emotet"| Tab | Panes |
|---|---|
π¬ static |
file/strings/objdump + disasm + hex + YARA |
π§ͺ dynamic |
strace/ltrace + sandbox + process & file monitors |
π network |
tcpdump + DNS + connection tracker + FakeNet |
π ioc |
Hash/VT lookups + strings + report |
zos # alias (session: "osint", cwd: ~/ops/osint)
zos-new target-co # creates ~/ops/osint/target-co, session "os-target-co"| Tab | Panes |
|---|---|
π― target |
whois/dig + Shodan/Censys + IP lookup + notes |
π web |
Wayback/archive + metadata + tech stack + certs |
π‘ social |
Username/email/phone/leak search |
ποΈ timeline |
Report + data correlation + evidence log |
Zellij sessions persist after you detach. You can have multiple sessions running simultaneously and switch between them.
zellij --session myname --layout project # start a named sessionIf a session with that name already exists, Zellij reattaches to it instead of creating a duplicate.
| Action | Command / Keybind |
|---|---|
| List sessions | zls |
| Attach to session | za <name> |
| Detach (keeps running) | Ctrl+o then d |
| Switch session (inside Zellij) | Ctrl+o then w |
| Kill one session | zks <name> |
| Kill all sessions | zka |
Zellij uses modes β press a key combo to enter a mode, do your thing, press Esc to exit.
| Action | Keybind |
|---|---|
| Enter tab mode | Ctrl+t |
| Next / previous tab | l / h (or β / β) |
| Go to tab by number | 1β9 |
| New tab | n |
| Rename tab | r |
| Action | Keybind |
|---|---|
| Enter pane mode | Ctrl+p |
| Move focus | h/j/k/l (or arrows) |
| Toggle full-screen | f |
| Action | Keybind |
|---|---|
| Enter scroll mode | Ctrl+s |
| Scroll | β/β or PgUp/PgDn |
| Search in output | s (then type) |
Full keybinding reference: zellij.dev/documentation/keybindings
Add these aliases and functions to your .zshrc or .bashrc:
# Zellij
alias z='zellij'
# Layouts (with named sessions)
alias zp='zellij --session claude --layout claude-projects'
alias zo='zellij --layout project options --default-cwd'
alias zdk='zellij --session docker --layout docker options --default-cwd ~/docker'
alias zpt='zellij --session pentest --layout pentest options --default-cwd ~/ops/pentest'
alias zma='zellij --session malware --layout malware-analysis options --default-cwd ~/ops/malware'
alias zos='zellij --session osint --layout osint options --default-cwd ~/ops/osint'
# Session management
alias zls='zellij list-sessions'
alias za='zellij attach'
alias zks='zellij kill-session'
alias zka='rm -rf ~/.cache/zellij'These create a fresh directory and launch a named session in one step:
# zpt-new acme β ~/ops/pentest/acme, session "pt-acme"
# zma-new emotet β ~/ops/malware/emotet, session "ma-emotet"
# zos-new corp β ~/ops/osint/corp, session "os-corp"
# zdk-new stack β ~/docker/stack, session "dk-stack"
# zp-new my-app β ~/projects/my-app, session "my-app"
zpt-new() {
[[ -z "$1" ]] && { echo "Usage: zpt-new <name>"; return 1; }
mkdir -p "$HOME/ops/pentest/$1"
zellij --session "pt-$1" --layout pentest options --default-cwd "$HOME/ops/pentest/$1"
}
zma-new() {
[[ -z "$1" ]] && { echo "Usage: zma-new <name>"; return 1; }
mkdir -p "$HOME/ops/malware/$1"
zellij --session "ma-$1" --layout malware-analysis options --default-cwd "$HOME/ops/malware/$1"
}
zos-new() {
[[ -z "$1" ]] && { echo "Usage: zos-new <name>"; return 1; }
mkdir -p "$HOME/ops/osint/$1"
zellij --session "os-$1" --layout osint options --default-cwd "$HOME/ops/osint/$1"
}
zdk-new() {
[[ -z "$1" ]] && { echo "Usage: zdk-new <name>"; return 1; }
mkdir -p "$HOME/docker/$1"
zellij --session "dk-$1" --layout docker options --default-cwd "$HOME/docker/$1"
}
zp-new() {
[[ -z "$1" ]] && { echo "Usage: zp-new <name>"; return 1; }
mkdir -p "$HOME/projects/$1"
zellij --session "$1" --layout project options --default-cwd "$HOME/projects/$1"
}This is the only generated layout. Edit the projects array in generate-layout.sh:
projects=(
"my-app:π::logs/dev.log" # dirname:emoji:label:logfile
"api:π:backend-api:" # empty logfile β plain shell pane
)Format: "dirname:emoji:label:logfile"
dirnameβ subdirectory under~/projects/emojiβ tab iconlabelβ tab display name (defaults to dirname if empty)logfileβ path to tail relative to project dir (omit for plain shell)
Then run make install.
make # regenerate claude-projects.kdl
make install # lint + regenerate + install all layouts
make uninstall # remove installed layouts (keeps local files)
make clean # remove generated + installed files
make setup # create ~/ops/{pentest,malware,osint}
make lint # validate KDL brace balance
make list # show installed layouts
make help # show all targets
- Keybind conflicts? Press
Ctrl+gto enter locked mode β all keys pass through to the app (e.g. Claude Code). PressCtrl+gagain to unlock and use Zellij keybinds. - Reattach, don't relaunch. Running
zpttwice reattaches to the existing "pentest" session β it won't create a duplicate. - Full-screen a pane with
Ctrl+p fwhen you need more space, thenCtrl+p fagain to restore. - Scroll back with
Ctrl+sβ useful for reading long command output. Presssinside scroll mode to search. - Rename tabs with
Ctrl+t rβ handy for per-engagement tabs in the security layouts. - Floating pane with
Ctrl+p wβ spawns a temporary pane on top without changing your layout. - Sync panes β
Ctrl+t stoggles sync mode: type in one pane, it echoes to all panes in the tab. Great for running the same command across multiple shells. - Copy mode β
Ctrl+sthen select text with arrows +Enter. Works without mouse. - Pipe pane output β
zellij pipelets you send pane output to external scripts.
More tips: zellij.dev/documentation