diff --git a/pressure-vessel/launch.1.md b/pressure-vessel/launch.1.md
index 182eaa74dbbf5a1aedb3c05ebce1f08ea3153659..e835417c156e5d9be87479700e64fb292294c902 100644
--- a/pressure-vessel/launch.1.md
+++ b/pressure-vessel/launch.1.md
@@ -72,6 +72,15 @@ as a subprocess of **pressure-vessel-launcher**.
     As with **org.freedesktop.Flatpak**, the
     **--terminate** option is not allowed in this mode.
 
+**--app-path** *PATH*, **--app-path=**
+:   When creating a Flatpak subsandbox, mount *PATH* as the `/app` in
+    the new subsandbox. If *PATH* is specified as the empty string,
+    place an empty directory at `/app`.
+
+    This experimental option is only valid when used with
+    **--bus-name=org.freedesktop.portal.Flatpak**, and requires a
+    Flatpak branch that has not yet been merged.
+
 **--clear-env**
 :   The *COMMAND* runs in an empty environment, apart from any environment
     variables set by **--env** and similar options.
@@ -102,6 +111,14 @@ as a subprocess of **pressure-vessel-launcher**.
 **--terminate**
 :   Instead of running a *COMMAND*, terminate the Launcher server.
 
+**--usr-path** *PATH*
+:   When creating a Flatpak subsandbox, mount *PATH* as the `/usr` in
+    the new subsandbox.
+
+    This experimental option is only valid when used with
+    **--bus-name=org.freedesktop.portal.Flatpak**, and requires a
+    Flatpak branch that has not yet been merged.
+
 **--verbose**
 :   Be more verbose.
 
diff --git a/pressure-vessel/launch.c b/pressure-vessel/launch.c
index 66facac6573c2a5ea52766465c028a66861f2f8b..d000f1386bb925723af0c7c088b59e62b030ecf0 100644
--- a/pressure-vessel/launch.c
+++ b/pressure-vessel/launch.c
@@ -55,6 +55,7 @@ typedef enum {
   FLATPAK_SPAWN_FLAGS_EXPOSE_PIDS = 1 << 5, /* Since 1.6, optional */
   FLATPAK_SPAWN_FLAGS_NOTIFY_START = 1 << 6,
   FLATPAK_SPAWN_FLAGS_SHARE_PIDS = 1 << 7,
+  FLATPAK_SPAWN_FLAGS_EMPTY_APP = 1 << 8,
 } FlatpakSpawnFlags;
 
 typedef enum {
@@ -475,7 +476,84 @@ check_portal_supports (const char *option, guint32 supports_needed)
     }
 }
 
+static gint32
+path_to_handle (GUnixFDList *fd_list,
+                const char *path,
+                const char *home_realpath,
+                const char *flatpak_id,
+                GError **error)
+{
+  int path_fd = open (path, O_PATH|O_CLOEXEC|O_NOFOLLOW|O_RDONLY);
+  int saved_errno;
+  gint32 handle;
+
+  if (path_fd < 0)
+    {
+      saved_errno = errno;
+      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno),
+                   "Failed to open %s to expose in sandbox: %s",
+                   path, g_strerror (saved_errno));
+      return -1;
+    }
+
+  if (home_realpath != NULL && flatpak_id != NULL)
+    {
+      g_autofree char *real = NULL;
+      const char *after = NULL;
+
+      real = realpath (path, NULL);
+
+      if (real != NULL)
+        after = pv_get_path_after (real, home_realpath);
+
+      if (after != NULL)
+        {
+          g_autofree char *var_path = NULL;
+          int var_fd = -1;
+          struct stat path_buf;
+          struct stat var_buf;
+
+          /* @after is possibly "", but that's OK: if @path is exactly $HOME,
+           * we want to check whether it's the same file as
+           * ~/.var/app/$FLATPAK_ID, with no suffix */
+          var_path = g_build_filename (home_realpath, ".var", "app", flatpak_id,
+                                       after, NULL);
+
+          var_fd = open (var_path, O_PATH|O_CLOEXEC|O_NOFOLLOW|O_RDONLY);
+
+          if (var_fd >= 0 &&
+              fstat (path_fd, &path_buf) == 0 &&
+              fstat (var_fd, &var_buf) == 0 &&
+              path_buf.st_dev == var_buf.st_dev &&
+              path_buf.st_ino == var_buf.st_ino)
+            {
+              close (path_fd);
+              path_fd = var_fd;
+              var_fd = -1;
+            }
+          else
+            {
+              close (var_fd);
+            }
+        }
+    }
+
+
+  handle = g_unix_fd_list_append (fd_list, path_fd, error);
+
+  if (handle < 0)
+    {
+      g_prefix_error (error, "Failed to add fd to list for %s: ", path);
+      return -1;
+    }
+
+  /* The GUnixFdList keeps a duplicate, so we should release the original */
+  close (path_fd);
+  return handle;
+}
+
 static gchar **forward_fds = NULL;
+static gchar *opt_app_path = NULL;
 static gboolean opt_clear_env = FALSE;
 static gchar *opt_dbus_address = NULL;
 static gchar *opt_directory = NULL;
@@ -484,6 +562,7 @@ static GHashTable *opt_env = NULL;
 static GHashTable *opt_unsetenv = NULL;
 static gboolean opt_share_pids = FALSE;
 static gboolean opt_terminate = FALSE;
+static gchar *opt_usr_path = NULL;
 static gboolean opt_verbose = FALSE;
 static gboolean opt_version = FALSE;
 
@@ -576,6 +655,11 @@ opt_env_cb (const char *option_name,
 
 static const GOptionEntry options[] =
 {
+  { "app-path", '\0',
+    G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_app_path,
+    "Use DIR as the /usr for a Flatpak sub-sandbox. "
+    "Requires '--bus-name=org.freedesktop.portal.Flatpak'.",
+    "DIR" },
   { "bus-name", '\0',
     G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &launcher_api.service_bus_name,
     "Connect to a Launcher service with this name on the session bus.",
@@ -608,6 +692,11 @@ static const GOptionEntry options[] =
   { "share-pids", '\0',
     G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_share_pids,
     "Use same pid namespace as calling sandbox.", NULL },
+  { "usr-path", '\0',
+    G_OPTION_FLAG_NONE, G_OPTION_ARG_FILENAME, &opt_usr_path,
+    "Use DIR as the /usr for a Flatpak sub-sandbox. "
+    "Requires '--bus-name=org.freedesktop.portal.Flatpak'.",
+    "DIR" },
   { "socket", '\0',
     G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &opt_socket,
     "Connect to a Launcher server listening on this AF_UNIX socket.",
@@ -655,6 +744,8 @@ main (int argc,
   gsize i;
   GHashTableIter iter;
   gpointer key, value;
+  g_autofree char *home_realpath = NULL;
+  const char *flatpak_id = NULL;
 
   setlocale (LC_ALL, "");
 
@@ -718,6 +809,11 @@ main (int argc,
 
   _srt_setenv_disable_gio_modules ();
 
+  flatpak_id = g_environ_getenv (original_environ, "FLATPAK_ID");
+
+  if (flatpak_id != NULL)
+    home_realpath = realpath (g_get_home_dir (), NULL);
+
   if (launcher_api.service_bus_name != NULL && opt_socket != NULL)
     {
       glnx_throw (error, "--bus-name and --socket cannot both be used");
@@ -740,6 +836,20 @@ main (int argc,
       goto out;
     }
 
+  if (api != &subsandbox_api && opt_app_path != NULL)
+    {
+      glnx_throw (error,
+                  "--app-path can only be used with a Flatpak subsandbox");
+      goto out;
+    }
+
+  if (api != &subsandbox_api && opt_usr_path != NULL)
+    {
+      glnx_throw (error,
+                  "--usr-path can only be used with a Flatpak subsandbox");
+      goto out;
+    }
+
   if (argc >= 2 && strcmp (argv[1], "--") == 0)
     {
       argv++;
@@ -953,6 +1063,68 @@ main (int argc,
 
   g_variant_builder_init (&options_builder, G_VARIANT_TYPE ("a{sv}"));
 
+  if (opt_app_path != NULL)
+    {
+      gint32 handle;
+
+      g_debug ("Using \"%s\" as /app instead of runtime", opt_app_path);
+
+      g_assert (api == &subsandbox_api);
+
+      if (g_getenv ("PRESSURE_VESSEL_FLATPAK_PR4018") == NULL)
+        {
+          glnx_throw (error,
+                      "--app-path requires an experimental branch of Flatpak");
+          goto out;
+        }
+
+      check_portal_version ("app-path", 6);
+
+      if (opt_app_path[0] == '\0')
+        {
+          /* Empty path is special-cased to mean an empty directory */
+          spawn_flags |= FLATPAK_SPAWN_FLAGS_EMPTY_APP;
+        }
+      else
+        {
+          handle = path_to_handle (fd_list, opt_app_path, home_realpath,
+                                   flatpak_id, error);
+
+          if (handle < 0)
+            goto out;
+
+          g_variant_builder_add (&options_builder, "{s@v}", "app-fd",
+                                 g_variant_new_variant (g_variant_new_handle (handle)));
+        }
+    }
+
+  if (opt_usr_path != NULL)
+    {
+      gint32 handle;
+
+      g_debug ("Using %s as /usr instead of runtime", opt_usr_path);
+
+      g_assert (api == &subsandbox_api);
+
+      if (g_getenv ("PRESSURE_VESSEL_FLATPAK_PR4018") == NULL)
+        {
+          glnx_throw (error,
+                      "--usr-path requires an experimental branch of Flatpak");
+          goto out;
+        }
+
+      check_portal_version ("usr-path", 6);
+
+      handle = path_to_handle (fd_list, opt_usr_path, home_realpath,
+                               flatpak_id, error);
+
+      if (handle < 0)
+        goto out;
+
+      g_variant_builder_add (&options_builder, "{s@v}", "usr-fd",
+                             g_variant_new_variant (g_variant_new_handle (handle)));
+    }
+
   if (opt_terminate)
     {
       g_assert (api == &launcher_api);
@@ -1113,10 +1285,12 @@ out:
     g_source_remove (signal_source);
 
   g_strfreev (forward_fds);
+  g_free (opt_app_path);
   g_free (opt_directory);
   g_free (opt_socket);
   g_hash_table_unref (opt_env);
   g_hash_table_unref (opt_unsetenv);
+  g_free (opt_usr_path);
   global_original_environ = NULL;
 
   g_debug ("Exiting with status %d", launch_exit_status);