# The rename: zellij → sl0ppij **Status: implemented.** See commit `sl0p: rename to sl0ppij behind a branding seam`. **Goal:** a machine can have stock zellij and sl0ppij installed at the same time, running at the same time, without sharing a single byte of state. ## Isolation checklist All disjoint from upstream as of the rename commit: | surface | upstream | sl0ppij | done | |---|---|---|---| | binary name | `zellij` | `sl0ppij` | ✅ | | config dir | `~/.config/zellij` | `~/.config/sl0ppij` | ✅ | | cache/data dir | `ProjectDirs("org","Zellij Contributors","Zellij")` | `ProjectDirs("foo","sl0p","sl0ppij")` | ✅ | | system config | `/etc/zellij` | `/etc/sl0ppij` | ✅ | | system data | `/usr/share/zellij` | `/usr/share/sl0ppij` | ✅ | | socket/tmp dir | `$TMPDIR/zellij-$UID` | `$TMPDIR/sl0ppij-$UID` | ✅ | | log dir/file | `…/zellij-log/zellij.log` | `…/sl0ppij-log/sl0ppij.log` | ✅ | | env vars | `ZELLIJ*` | `SL0PPIJ*` **and** `ZELLIJ*` (ours wins) | ✅ | | plugin URL scheme | `zellij:about` | `sl0ppij:about` (accepts `zellij:`) | ✅ | | help / CLI text | "zellij" | "sl0ppij" | ✅ | | default-plugin text | "zellij" | — | ⬜ needs a wasm rebuild | | desktop/shell assets | `assets/zellij.desktop`, `zellij.rc` | — | ⬜ packaging-only, unused so far | ## Where the work actually is Encouragingly small and centralised: - **`zellij-utils/src/consts.rs`** — the whole path story. Lines to touch: - `SYSTEM_DEFAULT_CONFIG_DIR` (`/etc/zellij`, and the Windows arm) - `ZELLIJ_PROJ_DIR` — `ProjectDirs::from("", "", "Zellij")` / `("org", "Zellij Contributors", "Zellij")` - `ZELLIJ_TMP_DIR` — `temp_dir().join(format!("zellij-{}", *UID))` - `ZELLIJ_TMP_LOG_DIR` / `ZELLIJ_TMP_LOG_FILE` — `zellij-log`, `zellij.log` - the non-unix arm's `tmp_dir.join("zellij")` - **`zellij-utils/src/envs.rs`** — `ZELLIJ_ENV_KEY`, `SESSION_NAME_ENV_KEY`, `SOCKET_DIR_ENV_KEY`. - **`zellij-utils/src/cli.rs:57`** — clap `name = "zellij"` (drives every usage string and `--help`). - **`zellij-utils/src/input/plugins.rs:77`** — builtin plugin URL scheme. - **`Cargo.toml`** — the root package `name = "zellij"` decides the binary name. *Renaming the package is the loudest possible change against upstream.* See "Strategy" below. - **`assets/zellij.desktop`, `assets/zellij.rc`**, `wix/`, `.github/` packaging bits. - **user-visible help strings** — `"zellij setup --check"`, `"zellij -l compact"` etc. inside `default-plugins/status-bar` tips and `about`. ## What was left out, on purpose - **`default-plugins/*` strings** (the About screen, status-bar tips) still say "zellij". They live inside prebuilt `.wasm` blobs in `zellij-utils/assets/plugins/`, so changing them means rebuilding the plugins and committing new binaries — a separate, chunky commit. - **`assets/zellij.desktop` / `zellij.rc`** are only used by distro packaging and the Windows build, neither of which we ship yet. - **Crate names** (`zellij-utils`, `zellij-tile`, …) — see below. ## Strategy: one seam, not a sed Do **not** `sed -i s/zellij/sl0ppij/g` the tree. Every touched upstream line is a rebase conflict forever, and there are ~3300 upstream commits of future rebases. Instead: 1. **Introduce a single branding module** (`zellij-utils/src/branding.rs`) with `pub const APP: &str = "sl0ppij";` plus derived consts (config dir name, tmp prefix, log names, env prefix, plugin scheme). 2. **Point the ~15 sites above at it.** Each becomes a one-line diff that reads `branding::APP` instead of a literal — small, stable, easy to re-apply. 3. **Keep the crate/package names as `zellij*`.** The *binary* name is set with `[[bin]] name = "sl0ppij"` instead of renaming the package, so all the intra-workspace `zellij-utils`/`zellij-tile` deps, plugin APIs and the `0.45.0+sl0p1` version trick keep working untouched. Nothing user-facing says "zellij" and nothing internal has to move. 4. **`ZELLIJ_EXECUTABLE_LOCATION` / self-exec**: the client re-execs itself to spawn the server. Verify it resolves via `current_exe()` and not a hardcoded `"zellij"` on `$PATH`, or a sl0ppij client will start a zellij server. ## Decided: env vars keep both spellings Renaming `ZELLIJ=0` → `SL0PPIJ=0` outright would break every third-party thing that detects "am I in a multiplexer" (shell prompts, starship, nested-session guards, and our own `pi-ext`). So **both are exported**, and `SL0PPIJ*` takes precedence on read: | variable | ours | upstream's | |---|---|---| | marker | `SL0PPIJ` | `ZELLIJ` | | session | `SL0PPIJ_SESSION_NAME` | `ZELLIJ_SESSION_NAME` | | pane | `SL0PPIJ_PANE_ID` | `ZELLIJ_PANE_ID` | | socket dir | `SL0PPIJ_SOCKET_DIR` | `ZELLIJ_SOCKET_DIR` | | config file/dir, layout dir | `SL0PPIJ_CONFIG_*`, `SL0PPIJ_LAYOUT_DIR` | `ZELLIJ_CONFIG_*`, `ZELLIJ_LAYOUT_DIR` | `branding::import_compat_env()` runs first thing in `main()` and folds an inherited `ZELLIJ_*` into its `SL0PPIJ_*` spelling, which is what makes the clap-derived arguments honour both (clap accepts only one env name per arg). Note the spelling is `SL0PPIJ` (zero), matching the binary name. > Because both spellings are exported, a pi running inside sl0ppij still sees > `$ZELLIJ`, so **pi-ext needed no changes**. ## Verification (all performed) **Unit tests** in `branding.rs`: no shipped default path contains the string `zellij`; env precedence is ours-then-upstream; `set_env_var` writes both spellings; every pair differs only by prefix. **Suites:** `zellij-utils` 471 passed, `zellij-server` 1499 passed. **Live, against a box already running stock zellij:** ``` $ sl0ppij --version -> sl0ppij 0.45.0+sl0p1 $ sl0ppij setup --check -> ~/.config/sl0ppij, ~/.cache/sl0ppij, /usr/share/sl0ppij $ ls -d /tmp/sl0ppij-1000 /tmp/zellij-1000 -> both exist, disjoint $ zellij list-sessions -> 3 sessions $ sl0ppij list-sessions -> "No active sl0ppij sessions found." ``` **Env precedence, end to end:** | set | resulting CONFIG DIR | |---|---| | `ZELLIJ_CONFIG_DIR=/tmp/cfg-upstream` | `/tmp/cfg-upstream` | | `SL0PPIJ_CONFIG_DIR=/tmp/cfg-ours` | `/tmp/cfg-ours` | | both | `/tmp/cfg-ours` | **Config:** the rebranded `config/config.kdl` loads under the renamed binary (`[CONFIG FILE]: Well defined.`).