Task
Install zellij terminal multiplexer and configure each shell profile (PowerShell and
WSL bash / zsh) to launch it automatically on startup — replacing any existing herdr
autostart block installed by setup-herdr.
Steps
1. Check Zellij installation (per environment)
PowerShell:
Run Get-Command zellij -ErrorAction SilentlyContinue (or zellij --version).
WSL:
Run wsl -- which zellij (or wsl -- zellij --version).
If found in an environment, mark that environment "already installed" and skip to step 3
for it. If not found, continue to step 2 for that environment.
2. Install Zellij (only after user confirmation)
These are system-level installers — always show the exact command and get the user's
go-ahead before running it via Bash/PowerShell (same convention setup-herdr uses for
herdr's own install script).
Windows:
winget install --id Zellij.Zellij -e
WSL/Linux:
sudo apt update && sudo apt install -y zellij
If the distribution doesn't ship zellij, install it from Cargo instead:
cargo install --locked zellij (or see https://zellij.dev).
If the user declines, mark that environment "skipped (declined)" and continue with the
other environment.
3. Configure shell profiles: remove herdr autostart, add Zellij autostart
Process the following four profiles independently: PowerShell 7 ($PROFILE),
Windows PowerShell, WSL bash, and WSL zsh (only if zsh is installed).
3-A. PowerShell 7 profile
Get the profile path from $PROFILE.
If the file does not exist, create it along with its parent directory.
Remove any existing herdr autostart block. Look for the # Auto-start herdr
comment; if present, remove it together with the block that follows through the
matching closing }:
# Auto-start herdr
if (-not $env:HERDR_ENV) {
herdr
}
If not found, note "(nothing to remove)" and continue.
Read the file and check whether it contains ZELLIJ or Auto-start Zellij.
If found, mark as "already configured" and skip to 3-B.
If not found, append the following at the end of the file:
# Auto-start Zellij
if (-not $env:ZELLIJ) {
$cwd = (Get-Location).Path
zellij options --default-shell pwsh --default-cwd $cwd
}
Why --default-cwd?
On Windows, Zellij does not inherit the CWD from the launching shell, so new
panes open in the user home directory. --default-cwd sets the working
directory for the Zellij session directly, without altering the shell command.
(pwsh = PowerShell 7 executable name on Windows)
3-B. Windows PowerShell profile
Build the profile path without hardcoding the username:
$winPSProfile = Join-Path ([Environment]::GetFolderPath("MyDocuments")) "WindowsPowerShell\Microsoft.PowerShell_profile.ps1"
OneDrive redirect: On systems where OneDrive syncs the Documents folder,
GetFolderPath("MyDocuments") returns the OneDrive path (e.g.
C:\Users\...\OneDrive\Documents\...). Do NOT hardcode
C:\Users\...\Documents\... — the actual profile will be on OneDrive and
the hardcoded path will silently miss it. Always use GetFolderPath or
resolve the path via PowerShell before reading/editing.
If the parent directory (WindowsPowerShell\) does not exist, create it with New-Item -ItemType Directory -Force.
If the file does not exist, create it.
Remove any existing herdr autostart block (same # Auto-start herdr → closing
} detection as 3-A). If not found, note "(nothing to remove)" and continue.
Read the file and check whether it contains ZELLIJ or Auto-start Zellij.
If found, mark as "already configured" and skip to 3-C.
If not found, append the following at the end of the file:
# Auto-start Zellij
if (-not $env:ZELLIJ) {
$cwd = (Get-Location).Path
zellij options --default-shell powershell --default-cwd $cwd
}
Why --default-cwd?
Same reason as 3-A. (powershell = Windows PowerShell 5.x executable name)
3-C. WSL bash profile
Run wsl -- test -f ~/.bashrc && echo exists to check whether ~/.bashrc exists.
Remove any existing herdr autostart block. Look for the # Auto-start herdr
comment; if present, remove it together with the block that follows through the
matching fi (e.g. wsl -- sed -i '/# Auto-start herdr/,/^fi$/d' ~/.bashrc — the
block shape is fixed and known, so a range delete from the comment through the next
^fi$ is safe). If not found, note "(nothing to remove)" and continue.
Run wsl -- grep -q "Auto-start Zellij" ~/.bashrc to check for duplicates.
(Match the literal comment marker Auto-start Zellij, not ZELLIJ — see the
warning below for why.) If already present, skip to 3-D.
If not present, append the block by piping a PowerShell single-quoted here-string
to WSL's stdin. The closing '@ must sit at column 0:
@'
# Auto-start Zellij
if [[ -z "$ZELLIJ" ]]; then
zellij
fi
'@ | wsl -- bash -c 'cat >> ~/.bashrc'
⚠️ Why a here-string, not printf?
A naive wsl -- bash -c 'printf "...\$ZELLIJ..." >> ~/.bashrc' passes the
format string through PowerShell → wsl → bash. The \$ZELLIJ escaping is
fragile and can be stripped, writing if [[ -z "" ]] instead of
if [[ -z "$ZELLIJ" ]]. Since [[ -z "" ]] is always true, Zellij then
launches unconditionally — including inside an existing session — causing
runaway nested Zellij/shell spawning that makes WSL unstable.
A single-quoted here-string is passed verbatim (no $ expansion in
PowerShell), and cat appends stdin as-is, so the $ZELLIJ guard survives.
For the same reason, the dedup check in step 3 greps for Auto-start Zellij
(always written) rather than ZELLIJ (lost when the guard breaks).
3-D. WSL zsh profile (only if zsh is installed)
Run wsl -- which zsh to check whether zsh is available. If not found, skip.
Run wsl -- test -f ~/.zshrc && echo exists to check whether ~/.zshrc exists.
Remove any existing herdr autostart block (same detection/removal as 3-C, applied
to ~/.zshrc). If not found, note "(nothing to remove)" and continue.
Run wsl -- grep -q "generate-auto-start" ~/.zshrc first. If present, zsh already
auto-starts Zellij via the official zellij setup --generate-auto-start zsh method;
mark as "already configured" and skip (do not add a second manual block).
Otherwise run wsl -- grep -q "Auto-start Zellij" ~/.zshrc to check for the manual
block. If already present, skip.
If neither is present, append the block via a PowerShell here-string piped to stdin
(same technique and rationale as bash; the closing '@ must sit at column 0):
@'
# Auto-start Zellij
if [[ -z "$ZELLIJ" ]]; then
zellij
fi
'@ | wsl -- zsh -c 'cat >> ~/.zshrc'
4. Report results (follow the Output Format below)
Output Format
## Zellij Setup
| Item | Status |
|---------------------------|---------------------------------------------------|
| Zellij install (Windows) | <Installed / Already installed / Skipped (declined)> |
| Zellij install (WSL/Linux)| <Installed / Already installed / Skipped (declined)> |
| Profile | herdr block removed | Zellij autostart | Profile Path |
|----------------------|----------------------|------------------------------------------------------|--------------|
| PowerShell 7 | <Yes / No / N/A> | <Added / Already configured> | <$PROFILE path> |
| Windows PowerShell | <Yes / No / N/A> | <Added / Already configured> | <Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1> |
| WSL bash | <Yes / No / N/A> | <Added / Already configured> | ~/.bashrc |
| WSL zsh | <Yes / No / N/A / zsh not installed> | <Added / Already configured / Already auto-starts via generate-auto-start> | ~/.zshrc |
### Actions taken
- <bulleted list of what was actually done>
### Next steps
- Open each shell in a new session and verify that Zellij starts automatically.
- If you are already inside a Zellij session, nested launches are suppressed via the `$ZELLIJ` variable.
1---2name: setup-zellij3description: Install Zellij and configure shell profiles to auto-launch Zellij on startup (replacing any existing herdr autostart block). Use when the user wants to install or configure Zellij's shell autostart.4---56## Task78Install `zellij` terminal multiplexer and configure each shell profile (PowerShell and9WSL bash / zsh) to launch it automatically on startup — replacing any existing herdr10autostart block installed by `setup-herdr`.1112## Steps1314### 1. Check Zellij installation (per environment)1516**PowerShell:**17Run `Get-Command zellij -ErrorAction SilentlyContinue` (or `zellij --version`).1819**WSL:**20Run `wsl -- which zellij` (or `wsl -- zellij --version`).2122If found in an environment, mark that environment "already installed" and skip to step 323for it. If not found, continue to step 2 for that environment.2425---2627### 2. Install Zellij (only after user confirmation)2829These are system-level installers — always show the exact command and get the user's30go-ahead before running it via Bash/PowerShell (same convention `setup-herdr` uses for31herdr's own install script).3233**Windows:**34```powershell35winget install --id Zellij.Zellij -e36```3738**WSL/Linux:**39```bash40sudo apt update && sudo apt install -y zellij41```4243> If the distribution doesn't ship `zellij`, install it from Cargo instead:44> `cargo install --locked zellij` (or see https://zellij.dev).4546If the user declines, mark that environment "skipped (declined)" and continue with the47other environment.4849---5051### 3. Configure shell profiles: remove herdr autostart, add Zellij autostart5253Process the following **four profiles** independently: PowerShell 7 (`$PROFILE`),54Windows PowerShell, WSL bash, and WSL zsh (only if zsh is installed).5556#### 3-A. PowerShell 7 profile57581. Get the profile path from `$PROFILE`.592. If the file does not exist, create it along with its parent directory.603. **Remove any existing herdr autostart block.** Look for the `# Auto-start herdr`61 comment; if present, remove it together with the block that follows through the62 matching closing `}`:63 ```powershell64 # Auto-start herdr65 if (-not $env:HERDR_ENV) {66 herdr67 }68 ```69 If not found, note "(nothing to remove)" and continue.704. Read the file and check whether it contains `ZELLIJ` or `Auto-start Zellij`.71 If found, mark as "already configured" and skip to 3-B.725. If not found, append the following at the end of the file:7374 ```powershell75 # Auto-start Zellij76 if (-not $env:ZELLIJ) {77 $cwd = (Get-Location).Path78 zellij options --default-shell pwsh --default-cwd $cwd79 }80 ```8182 > **Why `--default-cwd`?**83 > On Windows, Zellij does not inherit the CWD from the launching shell, so new84 > panes open in the user home directory. `--default-cwd` sets the working85 > directory for the Zellij session directly, without altering the shell command.86 > (`pwsh` = PowerShell 7 executable name on Windows)8788#### 3-B. Windows PowerShell profile89901. Build the profile path without hardcoding the username:9192 ```powershell93 $winPSProfile = Join-Path ([Environment]::GetFolderPath("MyDocuments")) "WindowsPowerShell\Microsoft.PowerShell_profile.ps1"94 ```9596 > **OneDrive redirect**: On systems where OneDrive syncs the Documents folder,97 > `GetFolderPath("MyDocuments")` returns the OneDrive path (e.g.98 > `C:\Users\...\OneDrive\Documents\...`). Do NOT hardcode99 > `C:\Users\...\Documents\...` — the actual profile will be on OneDrive and100 > the hardcoded path will silently miss it. Always use `GetFolderPath` or101 > resolve the path via PowerShell before reading/editing.1021032. If the parent directory (`WindowsPowerShell\`) does not exist, create it with `New-Item -ItemType Directory -Force`.1043. If the file does not exist, create it.1054. **Remove any existing herdr autostart block** (same `# Auto-start herdr` → closing106 `}` detection as 3-A). If not found, note "(nothing to remove)" and continue.1075. Read the file and check whether it contains `ZELLIJ` or `Auto-start Zellij`.108 If found, mark as "already configured" and skip to 3-C.1096. If not found, append the following at the end of the file:110111 ```powershell112 # Auto-start Zellij113 if (-not $env:ZELLIJ) {114 $cwd = (Get-Location).Path115 zellij options --default-shell powershell --default-cwd $cwd116 }117 ```118119 > **Why `--default-cwd`?**120 > Same reason as 3-A. (`powershell` = Windows PowerShell 5.x executable name)121122#### 3-C. WSL bash profile1231241. Run `wsl -- test -f ~/.bashrc && echo exists` to check whether `~/.bashrc` exists.1252. **Remove any existing herdr autostart block.** Look for the `# Auto-start herdr`126 comment; if present, remove it together with the block that follows through the127 matching `fi` (e.g. `wsl -- sed -i '/# Auto-start herdr/,/^fi$/d' ~/.bashrc` — the128 block shape is fixed and known, so a range delete from the comment through the next129 `^fi$` is safe). If not found, note "(nothing to remove)" and continue.1303. Run `wsl -- grep -q "Auto-start Zellij" ~/.bashrc` to check for duplicates.131 (Match the literal comment marker `Auto-start Zellij`, **not** `ZELLIJ` — see the132 warning below for why.) If already present, skip to 3-D.1334. If not present, append the block by piping a **PowerShell single-quoted here-string**134 to WSL's stdin. The closing `'@` must sit at column 0:135136 ```powershell137 @'138139 # Auto-start Zellij140 if [[ -z "$ZELLIJ" ]]; then141 zellij142 fi143 '@ | wsl -- bash -c 'cat >> ~/.bashrc'144 ```145146 > **⚠️ Why a here-string, not `printf`?**147 > A naive `wsl -- bash -c 'printf "...\$ZELLIJ..." >> ~/.bashrc'` passes the148 > format string through PowerShell → wsl → bash. The `\$ZELLIJ` escaping is149 > fragile and can be stripped, writing `if [[ -z "" ]]` instead of150 > `if [[ -z "$ZELLIJ" ]]`. Since `[[ -z "" ]]` is **always true**, Zellij then151 > launches unconditionally — including inside an existing session — causing152 > runaway nested Zellij/shell spawning that makes WSL unstable.153 > A single-quoted here-string is passed **verbatim** (no `$` expansion in154 > PowerShell), and `cat` appends stdin as-is, so the `$ZELLIJ` guard survives.155 > For the same reason, the dedup check in step 3 greps for `Auto-start Zellij`156 > (always written) rather than `ZELLIJ` (lost when the guard breaks).157158#### 3-D. WSL zsh profile (only if zsh is installed)1591601. Run `wsl -- which zsh` to check whether zsh is available. If not found, skip.1612. Run `wsl -- test -f ~/.zshrc && echo exists` to check whether `~/.zshrc` exists.1623. **Remove any existing herdr autostart block** (same detection/removal as 3-C, applied163 to `~/.zshrc`). If not found, note "(nothing to remove)" and continue.1644. Run `wsl -- grep -q "generate-auto-start" ~/.zshrc` first. If present, zsh already165 auto-starts Zellij via the official `zellij setup --generate-auto-start zsh` method;166 **mark as "already configured" and skip** (do not add a second manual block).1675. Otherwise run `wsl -- grep -q "Auto-start Zellij" ~/.zshrc` to check for the manual168 block. If already present, skip.1696. If neither is present, append the block via a PowerShell here-string piped to stdin170 (same technique and rationale as bash; the closing `'@` must sit at column 0):171172 ```powershell173 @'174175 # Auto-start Zellij176 if [[ -z "$ZELLIJ" ]]; then177 zellij178 fi179 '@ | wsl -- zsh -c 'cat >> ~/.zshrc'180 ```181182---183184### 4. Report results (follow the Output Format below)185186## Output Format187188```189## Zellij Setup190191| Item | Status |192|---------------------------|---------------------------------------------------|193| Zellij install (Windows) | <Installed / Already installed / Skipped (declined)> |194| Zellij install (WSL/Linux)| <Installed / Already installed / Skipped (declined)> |195196| Profile | herdr block removed | Zellij autostart | Profile Path |197|----------------------|----------------------|------------------------------------------------------|--------------|198| PowerShell 7 | <Yes / No / N/A> | <Added / Already configured> | <$PROFILE path> |199| Windows PowerShell | <Yes / No / N/A> | <Added / Already configured> | <Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1> |200| WSL bash | <Yes / No / N/A> | <Added / Already configured> | ~/.bashrc |201| WSL zsh | <Yes / No / N/A / zsh not installed> | <Added / Already configured / Already auto-starts via generate-auto-start> | ~/.zshrc |202203### Actions taken204- <bulleted list of what was actually done>205206### Next steps207- Open each shell in a new session and verify that Zellij starts automatically.208- If you are already inside a Zellij session, nested launches are suppressed via the `$ZELLIJ` variable.209```