From 37ac128b2b153ce84c936a344f6bef2bfe44a28a Mon Sep 17 00:00:00 2001 From: PerchunPak Date: Tue, 3 Mar 2026 14:43:49 +0100 Subject: [PATCH 1/2] zellij: rename package file name Separated into a separate commit for easier reviewing and `git blame` --- pkgs/by-name/ze/zellij/{package.nix => unwrapped.nix} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename pkgs/by-name/ze/zellij/{package.nix => unwrapped.nix} (100%) diff --git a/pkgs/by-name/ze/zellij/package.nix b/pkgs/by-name/ze/zellij/unwrapped.nix similarity index 100% rename from pkgs/by-name/ze/zellij/package.nix rename to pkgs/by-name/ze/zellij/unwrapped.nix From 6c6cee98a0f8603e6645b3ebe8875fd6f46318ac Mon Sep 17 00:00:00 2001 From: PerchunPak Date: Mon, 2 Mar 2026 19:26:40 +0100 Subject: [PATCH 2/2] zellijPlugins: init --- ci/OWNERS | 3 + pkgs/by-name/ze/zellij/package.nix | 35 ++++++++ pkgs/by-name/ze/zellij/plugins/README.md | 83 +++++++++++++++++++ pkgs/by-name/ze/zellij/plugins/default.nix | 53 ++++++++++++ .../ze/zellij/plugins/rust/default.nix | 25 ++++++ pkgs/by-name/ze/zellij/plugins/rust/jbz.nix | 32 +++++++ .../plugins/rust/vim-zellij-navigator.nix | 26 ++++++ .../ze/zellij/plugins/rust/zjframes.nix | 12 +++ .../ze/zellij/plugins/rust/zjstatus.nix | 30 +++++++ pkgs/by-name/ze/zellij/unwrapped.nix | 7 +- pkgs/top-level/all-packages.nix | 2 + 11 files changed, 303 insertions(+), 5 deletions(-) create mode 100644 pkgs/by-name/ze/zellij/package.nix create mode 100644 pkgs/by-name/ze/zellij/plugins/README.md create mode 100644 pkgs/by-name/ze/zellij/plugins/default.nix create mode 100644 pkgs/by-name/ze/zellij/plugins/rust/default.nix create mode 100644 pkgs/by-name/ze/zellij/plugins/rust/jbz.nix create mode 100644 pkgs/by-name/ze/zellij/plugins/rust/vim-zellij-navigator.nix create mode 100644 pkgs/by-name/ze/zellij/plugins/rust/zjframes.nix create mode 100644 pkgs/by-name/ze/zellij/plugins/rust/zjstatus.nix diff --git a/ci/OWNERS b/ci/OWNERS index 2c0f70b41ec2..6c79a07b74bf 100644 --- a/ci/OWNERS +++ b/ci/OWNERS @@ -526,3 +526,6 @@ pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @FlameFlag @johnrtitor # Radicle /pkgs/build-support/fetchradicle/ @NixOS/radicle /pkgs/build-support/fetchradiclepatch/ @NixOS/radicle + +# Zellij plugins +/pkgs/by-name/ze/zellij/plugins/ @PerchunPak diff --git a/pkgs/by-name/ze/zellij/package.nix b/pkgs/by-name/ze/zellij/package.nix new file mode 100644 index 000000000000..32013b52f0ae --- /dev/null +++ b/pkgs/by-name/ze/zellij/package.nix @@ -0,0 +1,35 @@ +{ + lib, + callPackage, + makeBinaryWrapper, + stdenvNoCC, + nix-update-script, + + extraPackages ? [ ], +}: +let + unwrapped = callPackage ./unwrapped.nix { }; +in +stdenvNoCC.mkDerivation { + inherit (unwrapped) version meta; + pname = "zellij"; + + __structuredAttrs = true; + strictDeps = true; + + src = unwrapped; + dontUnpack = true; + + nativeBuildInputs = [ makeBinaryWrapper ]; + buildPhase = '' + cp -rs --no-preserve=mode "$src" "$out" + + wrapProgram "$out/bin/zellij" \ + --prefix PATH : '${lib.makeBinPath extraPackages}' + ''; + + passthru = unwrapped.passthru or { } // { + inherit unwrapped; + updateScript = nix-update-script { attrPath = "zellij.unwrapped"; }; + }; +} diff --git a/pkgs/by-name/ze/zellij/plugins/README.md b/pkgs/by-name/ze/zellij/plugins/README.md new file mode 100644 index 000000000000..bf643ce98969 --- /dev/null +++ b/pkgs/by-name/ze/zellij/plugins/README.md @@ -0,0 +1,83 @@ +# Zellij plugins + +Zellij offers a Webassembly / WASI plugin system, allowing plugin developers to +develop plugins in many different languages. Currently, nixpkgs focuses only on +Rust plugins (the majority of them). + +Most of the plugins were generated using `nix-init` on [awesome-zellij]. +Excluded plugins from that list (should be packaged later anyway): + +- [bar-theme-config](https://github.com/allisonhere/zellij-bar-theme-config): not a plugin, but a separate application +- [fzf-zellij](https://github.com/k-kuroguro/fzf-zellij): [closed source](https://github.com/k-kuroguro/fzf-zellij/issues/1) +- [gitpod-zellij](https://github.com/ona-samples/gitpod.zellij): not a plugin, but a separate application? +- [opencode-zellij-namer](https://github.com/24601/opencode-zellij-namer): written in TypeScript, not Rust +- [theme-configurator](https://rosmur.github.io/zellij-theme-configurator/): not a plugin, but a separate application +- [yazelix](https://github.com/luccahuguet/yazelix): written in Nushell +- [zeco](https://github.com/julianbuettner/zeco): not a plugin, but a separate application? +- [zellij-load](https://github.com/Christian-Prather/zellij-load): has daemon, so that needs to be packaged too +- [zellij-vscode-toolkit](https://github.com/atoolz/zellij-vscode-toolkit): not a plugin, but a VSCode plugin +- [zellix](https://github.com/EmeraldPandaTurtle/zellix): written in Nushell +- [zj-quit](https://github.com/cristiand391/zj-quit): archived +- [zj-status-bar](https://github.com/cristiand391/zj-status-bar): archived +- [zrw](https://github.com/ivoronin/zrw): written in Go + +Contributions are welcome! + +[awesome-zellij]: https://github.com/zellij-org/awesome-zellij/blob/95fce2c02a2dcca33e4972eed3eba64d516693c9/README.md + +## Specifying runtime dependencies + +Runtime dependencies are packages, that will be used by the plugin inside +a Zellij session. Those are specified in `passthru.runtimeDeps` attribute from +`pkgsBuildBuild` attrset. + +Since we compile all plugins on WASI, everything that the plugin gets as +derivation arguments are also get compiled for WASI. However, `coreutils` is +not available on WASI and so is the vast majority of packages. This is why +runtime dependencies need to be specified from `pkgsBuildBuild` attrs set +(which points to the user's system). + +```nix +# assume we build the plugin on a x86_64-linux machine +{ + lib, + fetchFromGitHub, + rustPlatform, + + # these will be compiled for WASI, not x86_64-linux! + just, + bacon, + # but pkgsBuildBuild points to x86_64-linux + pkgsBuildBuild, +}: +rustPlatform.buildRustPackage (finalAttrs: { + pname = "jbz"; + version = "0.39.0"; + + src = fetchFromGitHub { + owner = "nim65s"; + repo = "jbz"; + tag = "v${finalAttrs.version}"; + hash = "sha256-3n3Bv3YDb1+MYJTTAmMkIgGY7kX9IVUoDNV4c/n0Ydo="; + }; + + cargoHash = "sha256-U+P2LlhmXwaZy2a2eigrg545HTuV1T01jZfUOEUQ5+w="; + + # this is the only way how to specify dependencies + passthru.runtimeDeps = with pkgsBuildBuild; [ + bacon + just + ]; + + meta = { + description = "Display your Just commands wrapped in Bacon"; + homepage = "https://github.com/nim65s/jbz"; + changelog = "https://github.com/nim65s/jbz/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ PerchunPak ]; + }; +}) +``` + +If you are wondering why `pkgsBuildBuild` is named like that, refer to +[the docs on cross-compilation](https://nixos.org/manual/nixpkgs/unstable/#possible-dependency-types). diff --git a/pkgs/by-name/ze/zellij/plugins/default.nix b/pkgs/by-name/ze/zellij/plugins/default.nix new file mode 100644 index 000000000000..2fd950c0504e --- /dev/null +++ b/pkgs/by-name/ze/zellij/plugins/default.nix @@ -0,0 +1,53 @@ +{ + lib, + callPackage, + nix-update-script, + stdenvNoCC, + zellij, +}: +let + # wrapper for changing the output path from directory to single file + # from /nix/store/...-zsm-static-wasm32-unknown-wasi-0.4.1/bin/zsm.wasm + # to /nix/store/...-zellij-plugin-zsm-0.4.1.wasm + wrapper = + attrName: pkg: + assert lib.assertMsg ( + !((lib.hasAttr "runtimeDeps" pkg) && (!lib.hasAttr "runtimeDeps" pkg.passthru)) + ) "Plugin ${pkg.pname} has specified `runtimeDeps` instead of `passthru.runtimeDeps`"; + stdenvNoCC.mkDerivation (finalAttrs: { + inherit (pkg) + pname + version + ; + name = "zellij-plugin-${finalAttrs.pname}-${finalAttrs.version}.wasm"; + + src = pkg; + + dontUnpack = true; + buildPhase = '' + resultFile=$(find "$src" -name '*.wasm') + if [ $(echo "$resultFile" | wc -l) -ne 1 ]; then + echo "The unwrapped plugin ($src) contains more than one WASM file" + echo "$resultFile" + exit 1 + fi + + # there should probably be `ln -s` here, but it produces a permission error for me + cp "$resultFile" "$out" + ''; + + passthru = pkg.passthru or { } // { + unwrapped = pkg; + updateScript = pkg.passthru.updateScript or nix-update-script { + attrPath = "zellijPlugins.${attrName}.unwrapped"; + }; + }; + + meta = pkg.meta // { + maintainers = pkg.meta.maintainers or [ ] ++ [ lib.maintainers.PerchunPak ]; + platforms = pkg.meta.platforms or zellij.platforms; + }; + }); + rustPlugins = lib.mapAttrs wrapper (callPackage ./rust { }); +in +rustPlugins // { inherit wrapper; } diff --git a/pkgs/by-name/ze/zellij/plugins/rust/default.nix b/pkgs/by-name/ze/zellij/plugins/rust/default.nix new file mode 100644 index 000000000000..4de3f7567f85 --- /dev/null +++ b/pkgs/by-name/ze/zellij/plugins/rust/default.nix @@ -0,0 +1,25 @@ +{ pkgsCross, lib }: +let + root = ./.; + pkgs' = pkgsCross.wasi32; + + call = name: override (pkgs'.callPackage (root + "/${name}") { }); + override = + pkg: + pkg.overrideAttrs (old: { + # these hacks are needed until https://github.com/NixOS/nixpkgs/pull/463720#pullrequestreview-3841639011 is resolved + nativeBuildInputs = old.nativeBuildInputs or [ ] ++ [ pkgs'.lld ]; + env = old.env or { } // { + RUSTFLAGS = old.env.RUSTFLAGS or "" + " -C linker=wasm-ld"; + }; + + meta = old.meta or { } // { + platforms = old.meta.platforms or lib.platforms.linux; + }; + }); +in +lib.pipe root [ + builtins.readDir + (lib.filterAttrs (name: _: name != "default.nix" && name != "README.md")) + (lib.mapAttrs' (name: _: lib.nameValuePair (lib.removeSuffix ".nix" name) (call name))) +] diff --git a/pkgs/by-name/ze/zellij/plugins/rust/jbz.nix b/pkgs/by-name/ze/zellij/plugins/rust/jbz.nix new file mode 100644 index 000000000000..f46df69e428e --- /dev/null +++ b/pkgs/by-name/ze/zellij/plugins/rust/jbz.nix @@ -0,0 +1,32 @@ +{ + lib, + fetchFromGitHub, + rustPlatform, + pkgsBuildBuild, +}: +rustPlatform.buildRustPackage (finalAttrs: { + pname = "jbz"; + version = "0.39.0"; + + src = fetchFromGitHub { + owner = "nim65s"; + repo = "jbz"; + tag = "v${finalAttrs.version}"; + hash = "sha256-3n3Bv3YDb1+MYJTTAmMkIgGY7kX9IVUoDNV4c/n0Ydo="; + }; + + cargoHash = "sha256-U+P2LlhmXwaZy2a2eigrg545HTuV1T01jZfUOEUQ5+w="; + + passthru.runtimeDeps = with pkgsBuildBuild; [ + bacon + just + ]; + + meta = { + description = "Display your Just commands wrapped in Bacon"; + homepage = "https://github.com/nim65s/jbz"; + changelog = "https://github.com/nim65s/jbz/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ PerchunPak ]; + }; +}) diff --git a/pkgs/by-name/ze/zellij/plugins/rust/vim-zellij-navigator.nix b/pkgs/by-name/ze/zellij/plugins/rust/vim-zellij-navigator.nix new file mode 100644 index 000000000000..6697d1138d8e --- /dev/null +++ b/pkgs/by-name/ze/zellij/plugins/rust/vim-zellij-navigator.nix @@ -0,0 +1,26 @@ +{ + lib, + rustPlatform, + fetchFromGitHub, +}: +rustPlatform.buildRustPackage (finalAttrs: { + pname = "vim-zellij-navigator"; + version = "0.3.0"; + + src = fetchFromGitHub { + owner = "hiasr"; + repo = "vim-zellij-navigator"; + tag = finalAttrs.version; + hash = "sha256-1zzY1Z8ZpiNTdFW+gKRYaRR+oCzMnbJA2szY0k24bGg="; + }; + + cargoHash = "sha256-AbfgDhQEbm5qULw2HHxG5EMCYdML4VhHxJaAqP2g3u0="; + + meta = { + description = "Seamless navigation between Zellij panes and Vim splits"; + homepage = "https://github.com/hiasr/vim-zellij-navigator"; + changelog = "https://github.com/hiasr/vim-zellij-navigator/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ PerchunPak ]; + }; +}) diff --git a/pkgs/by-name/ze/zellij/plugins/rust/zjframes.nix b/pkgs/by-name/ze/zellij/plugins/rust/zjframes.nix new file mode 100644 index 000000000000..330d63676ae1 --- /dev/null +++ b/pkgs/by-name/ze/zellij/plugins/rust/zjframes.nix @@ -0,0 +1,12 @@ +{ callPackage }: +# zjstatus and zjframes are contained in the same repository, but as different crates +let + zjstatus = callPackage ./zjstatus.nix { _binaryName = "zjframes"; }; +in +zjstatus.overrideAttrs (old: { + pname = "zjframes"; + + meta = old.meta // { + description = "Toggle Zellij pane frames based on different conditions"; + }; +}) diff --git a/pkgs/by-name/ze/zellij/plugins/rust/zjstatus.nix b/pkgs/by-name/ze/zellij/plugins/rust/zjstatus.nix new file mode 100644 index 000000000000..d9418642f7a8 --- /dev/null +++ b/pkgs/by-name/ze/zellij/plugins/rust/zjstatus.nix @@ -0,0 +1,30 @@ +{ + lib, + fetchFromGitHub, + rustPlatform, + + _binaryName ? "zjstatus", # passed to `cargo build --bin` +}: +rustPlatform.buildRustPackage (finalAttrs: { + pname = "zjstatus"; + version = "0.23.0"; + + src = fetchFromGitHub { + owner = "dj95"; + repo = "zjstatus"; + tag = "v${finalAttrs.version}"; + hash = "sha256-sjMs63OaRhwCrl46v1A+K2EJdqnw63Pc7BMnHqiU790="; + }; + + cargoHash = "sha256-jg7EpcA3o/Qdb1eIspZQI3TX3+7gc3YX+FB4l4FZX44="; + + cargoBuildFlags = [ "--bin=${_binaryName}" ]; + + meta = { + description = "Configurable statusbar plugin for Zellij"; + homepage = "https://github.com/dj95/zjstatus"; + changelog = "https://github.com/dj95/zjstatus/releases/tag/${finalAttrs.src.tag}"; + license = lib.licenses.mit; + maintainers = with lib.maintainers; [ PerchunPak ]; + }; +}) diff --git a/pkgs/by-name/ze/zellij/unwrapped.nix b/pkgs/by-name/ze/zellij/unwrapped.nix index 06ef857d59ba..f691bc5418b2 100644 --- a/pkgs/by-name/ze/zellij/unwrapped.nix +++ b/pkgs/by-name/ze/zellij/unwrapped.nix @@ -10,11 +10,10 @@ openssl, writableTmpDirAsHomeHook, versionCheckHook, - nix-update-script, }: rustPlatform.buildRustPackage (finalAttrs: { - pname = "zellij"; + pname = "zellij-unwrapped"; version = "0.44.3"; __structuredAttrs = true; @@ -71,14 +70,12 @@ rustPlatform.buildRustPackage (finalAttrs: { installManPage zellij.1 '' + lib.optionalString (stdenv.buildPlatform.canExecute stdenv.hostPlatform) '' - installShellCompletion --cmd $pname \ + installShellCompletion --cmd zellij \ --bash <($out/bin/zellij setup --generate-completion bash) \ --fish <($out/bin/zellij setup --generate-completion fish) \ --zsh <($out/bin/zellij setup --generate-completion zsh) ''; - passthru.updateScript = nix-update-script { }; - meta = { description = "Terminal workspace with batteries included"; homepage = "https://zellij.dev/"; diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index c4ecea237155..5419f21c4086 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -3511,6 +3511,8 @@ with pkgs; nvidiaSupport = true; }; + zellijPlugins = recurseIntoAttrs (callPackage ../by-name/ze/zellij/plugins { }); + zstd = callPackage ../tools/compression/zstd { cmake = buildPackages.cmakeMinimal; };