How to install xdg-desktop-portal-termfilechooser?

How can I install and configure xdg-desktop-portal-termfilechooser?

I tried this in my configuration.nix:

xdg.portal = {
  enable = true;
  extraPortals = [ pkgs.xdg-desktop-portal-gtk pkgs.xdg-desktop-portal-termfilechooser ];
};

but that didn’t seem to work.

It works, but you need to do more.
Look at Add xdg-desktop-portal-termfilechooser and associated module by soispha · Pull Request #277531 · NixOS/nixpkgs · GitHub for inspiration.

Thanks for the link. I tries this but couldn’t get it to work:

xdg.portal = {
  enable = true;
  # Install the portal.
  extraPortals = [ pkgs.xdg-desktop-portal-gtk pkgs.xdg-desktop-portal-termfilechooser
  ];
  # Override the default filechooser portal.
  config = {
    my-random-wm = {
      default = [ "my-random-wm" "gtk" ];
      "org.freedesktop.impl.portal.FileChooser" = [ "xdg-desktop-portal-termfilechooser" ];
    };
  };
};
# Set it up.
environment.etc."xdg/xdg-desktop-portal-termfilechooser/config".text = ''
  [filechooser]
  cmd=/home/user/.config/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh
'';

After making these changes, when I run zenity --file-selection to test, I get the following:

(zenity:19892): Gdk-WARNING **: 12:27:58.234: Failed to read portal settings: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: No such interface “org.freedesktop.portal.Settings” on object at path /org/freedesktop/portal/desktop
MESA-INTEL: warning: ../src/intel/vulkan/anv_formats.c:802: FINISHME: support YUV colorspace with DRM format modifiers
MESA-INTEL: warning: ../src/intel/vulkan/anv_formats.c:834: FINISHME: support more multi-planar formats with DRM modifiers
Gtk-Message: 12:27:58.548: GtkDialog mapped without a transient parent. This is discouraged.

(zenity:19892): Gtk-WARNING **: 12:27:58.585: Unable to retrieve the Flatpak portal version: GDBus.Error:org.freedesktop.DBus.Error.ServiceUnknown: The name org.freedesktop.portal.Flatpak was not provided by any .service files

Any help would be greatly appreciated.

FWIW, I was able to get it working, using Home-Manager and Kitty. Of course, your mileage may vary with other terminals and without home-manager, but this does function, so maybe it’ll be helpful as a reference.

xdg.portal =
{
  enable = true;
  extraPortals = with pkgs-unstable;
  [
    xdg-desktop-portal-wlr
    xdg-desktop-portal-termfilechooser
  ];
};

xdg.portal.config.common =
{
  "org.freedesktop.impl.portal.FileChooser" = "termfilechooser";
};

home.sessionVariables.TERMCMD = "kitty --class=file_chooser";

xdg.configFile."xdg-desktop-portal-termfilechooser/config" =
{
  force = true;
  text =
  ''
    [filechooser]
    cmd=${pkgs-unstable.xdg-desktop-portal-termfilechooser}/share/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh
  '';
};

hey guys. :smiley:

i also am trying to set up xdg-desktop-portal-termfilechooser (without the gtk portal!) for hyprland AND lxqt. i have gotten to successfully launching the service via

xdg.portal.config = {
  common.default = [ "hyprland" ]; 
  common."org.freedesktop.impl.portal.FileChooser" = [ "termfilechooser" ]; 
  hyprland.default = [ "hyprland" ]; 
  hyprland."org.freedesktop.impl.portal.FileChooser" = [ "termfilechooser" ]; 
  lxqt.default = [ "lxqt" "hyprland" ];
  lxqt."org.freedesktop.impl.portal.FileChooser" = [ "termfilechooser" ]; 
};

(probably an overkill… oh, btw, should i use ["termfilechooser"] or ["xdg-desktop-portal-termfilechooser"]? i mean, it launches the service either way, but you never know, haha! thanks!)

but it still seem to not work… :woozy_face: i am using wezterm terminal and yazi file manager on 25.05 Warbler using flakes.

i have read the latest pr for termfilemanager but nothing worked. with or without a config present in $XDG_CONFIG_HOME (which ive copied from /nix/store/6jx8d0l715k9n6p99dd7i7jyjmxiiqha-xdg-desktop-portal-termfilechooser-1.0.5/share/xdg-desktop-portal-termfilechooser) it says:

apr 14 12:18:20 host xdg-desktop-portal-termfilechooser[1923]: sh: regel 1: yazi-wrapper.sh: opdracht niet gevonden
apr 14 12:18:20 host xdg-desktop-portal-termfilechooser[1454]: 2025/04/14 12:18:20 [ERROR] - filechooser: could not execute 'yazi-wrapper.sh 0 0 0 '/home/user' '/tmp/termfilechooser-1000.portal'': exit code -127

the “line 1” in yazi-wrapper.sh is:

#!/nix/store/58br4vk3q5akf4g8lx0pqzfhn47k3j8d-bash-5.2p37/bin/sh

am i doing something wrong? i probably am… sorry :sob:

P.S. im a bit suspicious of the yazi-wrapper.sh… even IF it passes the first line, what is it going to do with termcmd="${TERMCMD:-kitty --title 'termfilechooser'}"? im not using kitty… is this where you make your own config in ~/.config/xdg-desktop-portal-termfilechooser/? okay, but wezterm doesnt have a --title option or --class? im really lost… :frowning:

@frozen.frog23
I am using an external script for yazi which you can replace kitty terminal with any other terminal you want.

  • Create this directory:
    ~/.config/xdg-desktop-portal-termfilechooser
  • Create this file with the following content:
    ~/.config/xdg-desktop-portal-termfilechooser/config
[filechooser]
cmd=$HOME/.config/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh
default_dir=$HOME/Downloads
  • You can change cmd to any other path and modify the wrapper.
1 Like

okay. i tried it again with the user config in ~/.config/xdg-desktop-portal-termfilechooser. my yazi-config.sh looks thusly:

#!/bin/sh

set -ex
PATH="/usr/bin:/bin"

multiple="$1"
directory="$2"
save="$3"
path="$4"
out="$5"

cmd="yazi"
termcmd="wezterm start --always-new-process"

if [ "$save" = "1" ]; then
    # save a file
    set -- --chooser-file="$out" "$path"
elif [ "$directory" = "1" ]; then
    # upload files from a directory
    set -- --chooser-file="$out" --cwd-file="$out" "$path"
elif [ "$multiple" = "1" ]; then
    # upload multiple files
    set -- --chooser-file="$out" "$path"
else
    # upload only 1 file
    set -- --chooser-file="$out" "$path"
fi

command="$termcmd $cmd"
for arg in "$@"; do
    # escape double quotes
    escaped=$(printf "%s" "$arg" | sed 's/"/\\"/g')
    # escape spaces
    command="$command \"$escaped\""
done

sh -c "$command"

(btw this requires pkgs.gnused installed!)

notice two things: i changed the first line - it is not the default #!/nix/store/58br4vk3q5akf4g8lx0pqzfhn47k3j8d-bash-5.2p37/bin/sh, which fails immediately that i have mentioned previously. then, notice the

termcmd="wezterm start --always-new-process"

i looked it up on reddit (i hope you guys switch to lemmy!) and i hope it is the correct alternative to --title or --class of the kitty terminal for wezterm… just reminding you that im using wezterm terminal with yazi instead…

but it fails anyway after i try GDK_DEBUG=portals zenity --file-selection for testing if it opens wezterm with yazi:

apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + cmd=yazi
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + termcmd='wezterm start --always-new-process'
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + '[' 0 = 1 ']'
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + '[' 0 = 1 ']'
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + '[' 0 = 1 ']'
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + set -- --chooser-file=/tmp/termfilechooser-1000.portal /home/user/Downloads
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + command='wezterm start --always-new-process yazi'
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + for arg in "$@"
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1965]: + escaped=
apr 14 16:11:12 host xdg-desktop-portal-termfilechooser[1298]: 2025/04/14 16:11:12 [ERROR] - filechooser: could not execute '/home/user/.config/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh 0 0 0 '/home/user/Downloads' '/tmp/termfilechooser-1000.portal'': exit code -127

…no, it doesnt. no idea what is going on, but yeah, its no worky… :sob:

i would prefer not to use foot or kitty… is it not possible? i am sure i am not the only one here :crazy_face:

the subreddit is unofficial and unaffiliated with the nixos org, there’s some overlap with here but not much IME.

Anyway, I’m not sure what foot or kitty has to do with this discussion, but I see one problem: you set PATH to use some paths that don’t even necessarily exist on NixOS. Your shebang may also not work if you don’t have /bin/sh.

1 Like

oh my god. i just deleted/commented out the

PATH="/usr/bin:/bin"

and with GDK_DEBUG=portals zenity --file-selection albeit with some theme GtkSettings error screaming at me IT WORKED!!! :tada: :tada: :partying_face:

but wait, i need to test a few things first…

nevermind, celebrated too early… in hyprland it says this:

apr 14 16:53:30 host xdg-desktop-portal-termfilechooser[1838]: 16:53:30.560  WARN   window::os::wayland::connection > Unable to resolve appearance using xdg-desktop-portal: get_appearance.read_setting: Reading xdg-portal org.freedesktop.appearance color-scheme: org.freedesktop.DBus.Error.UnknownMethod: Interface ‘org.freedesktop.portal.Settings’ op object met pad /org/freedesktop/portal/desktop bestaat niet
apr 14 16:53:43 host xdg-desktop-portal-termfilechooser[1585]: 2025/04/14 16:53:43 [ERROR] - filechooser: failed to open '/tmp/termfilechooser-1000.portal' in read mode.

apart from the other spam that ive mentioned before, these are new and sound pretty spooky…

ok, heres what GDK_DEBUG=portals zenity --file-selection outputs:

(zenity:4111): Gdk-WARNING **: 17:02:53.799: Failed to read portal settings: GDBus.Error:org.freedesktop.DBus.Error.UnknownMethod: Interface ‘org.freedesktop.portal.Settings’ op object met pad /org/freedesktop/portal/desktop bestaat niet

(zenity:4111): Adwaita-WARNING **: 17:02:53.889: Using GtkSettings:gtk-application-prefer-dark-theme with libadwaita is unsupported. Please use AdwStyleManager:color-scheme instead.

EDIT: okay actually it says many different things with many different configs and none seem to work!

okay. :triumph: i THINK i have finally managed it to work without home-manager and whatever, but ONLY for firefox/librewolf… theres a few problems though - it doesnt look like it works for steam, messengers, and etc., - for 25.05 using flakes, that is. problem two is that those errors i mentioned earlier didnt really go away… anyway, here is what i have done:

this is for wezterm and yazi
configuration.nix

# ...

environment.variables = {
  GTK_USE_PORTAL = "1"; # legacy
  GDK_DEBUG = "portals"; # termfilechooser
};

xdg = {
  mime.enable = true;
  mime.defaultApplications = {
    "application/x-gnome-saved-search" = "yazi.desktop";
    "application/x-directory" = "yazi.desktop";
    "inode/directory" = "yazi.desktop";
    "x-directory/normal" = "yazi.desktop";
    "x-scheme-handler/trash" = "yazi.desktop";
  };
  portal = {
    enable = true;
    # xdgOpenUsePortal = true; # NIXOS_XDG_OPEN_USE_PORTAL
    config = {
      common.default = [ "hyprland" ]; 
      common."org.freedesktop.impl.portal.FileChooser" = [ "termfilechooser" ]; # xdg-?
      hyprland.default = [ "hyprland" ]; 
      hyprland."org.freedesktop.impl.portal.FileChooser" = [ "termfilechooser" ]; # xdg-?
      lxqt.default = [ "lxqt" "hyprland" ];
      lxqt."org.freedesktop.impl.portal.FileChooser" = [ "termfilechooser" ]; # xdg-?
    };
    extraPortals = [
      pkgs.xdg-desktop-portal-hyprland
      # pkgs.lxqt.xdg-desktop-portal-lxqt # works without!
      pkgs.xdg-desktop-portal-termfilechooser 
    ];
  };
};

# ...

xdgOpenUsePortal should be false because termfilechooser is just a backend and not a portal, and should only be used for saving / picking dialogues, etc… i mean, it broke steam for me, for example! …but maybe im just silly.

~/.config/xdg-desktop-portal-termfilechooser/config

[filechooser]
cmd=$HOME/.config/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh
default_dir=$HOME/Downloads

~/.config/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh

#!/bin/sh

set -ex

multiple="$1"
directory="$2"
save="$3"
path="$4"
out="$5"
cmd="yazi"
termcmd="${TERMCMD:-wezterm start --always-new-process}"

if [ "$save" = "1" ]; then
    set -- --chooser-file="$out" "$path"
elif [ "$directory" = "1" ]; then
    set -- --chooser-file="$out" --cwd-file="$out" "$path"
elif [ "$multiple" = "1" ]; then
    set -- --chooser-file="$out" "$path"
else
    set -- --chooser-file="$out" "$path"
fi

command="$termcmd $cmd"
for arg in "$@"; do
    escaped=$(printf "%s" "$arg" | sed 's/"/\\"/g')
    command="$command \"$escaped\""
done

sh -c "$command"

librewolf/firefox about:config

widget.use-xdg-desktop-portal.file-picker = 1

so… all that just for browser’s “save as” dialogue… :sob: i probably broke something anyway…

is there a way to “enforce” it to apply to ALL applications? or at least specific apps? :woozy_face:

FYI I have opened a PR on xdg-desktop-portal-termfilechooser to make the launcher scripts non-FHS specific, which was the main problem I think.

With this we can specify the PATH directly in the config, without keeping a modified launcher script copy.
This is my config, using the PR:

    xdg.configFile."xdg-desktop-portal-termfilechooser/config".text = let
      launcherDeps = pkgs.buildEnv {
        name = "yazi-launcher-dependencies";
        paths = with pkgs; [
          coreutils
          yazi
          gnused
          bashInteractive
        ];
      };
    in ''
      [filechooser]
      env=PATH='${launcherDeps}/bin'
      env=TERMCMD='${pkgs.foot}/bin/foot'
      cmd='${pkgs.xdg-desktop-portal-termfilechooser}/share/xdg-desktop-portal-termfilechooser/yazi-wrapper.sh'
      default_dir=$HOME/Downloads
    '';