diff --git a/bin/meson.build b/bin/meson.build
index d9b667ccbd838c3a23c010fcd4b7a265ba0f66f7..8604b408549ae78432cd1add5e49d14255049c71 100644
--- a/bin/meson.build
+++ b/bin/meson.build
@@ -51,10 +51,21 @@ executable(
   install_rpath : bin_rpath,
 )
 
+executable(
+  'steam-runtime-steam-remote',
+  'steam-remote.c',
+  dependencies : [glib, gio_unix, libglnx_dep, libsteamrt_static_dep],
+  install : true,
+  # Use GLib from the adjacent libdir, ignoring LD_LIBRARY_PATH
+  build_rpath : bin_rpath,
+  install_rpath : bin_rpath,
+)
+
 if get_option('man')
   foreach bin_name : [
     'check-requirements',
     'input-monitor',
+    'steam-remote',
     'system-info',
   ]
     custom_target(
diff --git a/bin/steam-remote.c b/bin/steam-remote.c
new file mode 100644
index 0000000000000000000000000000000000000000..83d8005305316fe7ebbad6839c5d3c54dc5f61f0
--- /dev/null
+++ b/bin/steam-remote.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2021 Collabora Ltd.
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Stub Steam executable that tries to directly pass the given commands to
+ * the running Steam client.
+ */
+
+#include <libglnx.h>
+
+#include <glib.h>
+#include <glib-object.h>
+
+#include <steam-runtime-tools/utils-internal.h>
+
+int
+main (int argc,
+      const char **argv)
+{
+  static const char *default_argv[] = {"steam", "-foreground", NULL};
+  g_autoptr(GError) error = NULL;
+
+  if (argc <= 1)
+    {
+      /* If we don't have arguments, Steam is expected to send the command
+       * "-foreground" by default */
+      argv = default_argv;
+      argc = 2;
+    }
+
+  if (!_srt_steam_command_via_pipe (argv + 1, argc - 1, &error))
+    {
+      g_printerr ("steam-runtime-steam-remote: %s\n", error->message);
+      return EXIT_FAILURE;
+    }
+
+  return EXIT_SUCCESS;
+}
diff --git a/bin/steam-remote.md b/bin/steam-remote.md
new file mode 100644
index 0000000000000000000000000000000000000000..75aeb265128ede992afdbcc874357ba9fc005d1f
--- /dev/null
+++ b/bin/steam-remote.md
@@ -0,0 +1,55 @@
+---
+title: steam-runtime-steam-remote
+section: 1
+...
+
+# NAME
+
+steam-runtime-steam-remote - stub Steam executable
+
+# SYNOPSIS
+
+**steam-runtime-steam-remote** [*ARGUMENT*]...
+
+# DESCRIPTION
+
+**steam-runtime-steam-remote** passes its command-line arguments
+to the Steam client that is currently running, if any.
+
+The command-line arguments will typically be a single
+[steam: URL](https://developer.valvesoftware.com/wiki/Steam_browser_protocol)
+such as `steam://advertise/70`, but can include other
+[Steam command-line options](https://developer.valvesoftware.com/wiki/Command_Line_Options#Steam_.28Windows.29)
+such as `-foreground`.
+
+A typical use for **steam-runtime-steam-remote** is to add a symbolic
+link named **steam** to a directory in the **PATH**, so that when a
+game runs a command like `steam -foreground`, it will be converted into
+an inter-process communication to the Steam client that is already running.
+
+# OUTPUT
+
+If the commands are correctly passed, the output will be empty.
+
+On error, a human-readable message is shown on standard error.
+
+# EXIT STATUS
+
+0
+:   **steam-runtime-steam-remote** ran successfully
+
+Other Nonzero
+:   An error occurred.
+
+# EXAMPLES
+
+Bring Steam's graphical user interface to the foreground:
+
+    steam-runtime-steam-remote -foreground
+
+Attempt to install Half-Life:
+
+    steam-runtime-steam-remote steam://install/70
+
+
+<!-- vim:set sw=4 sts=4 et: -->
diff --git a/debian/steam-runtime-tools-bin.install b/debian/steam-runtime-tools-bin.install
index 47904f91da17e9501c4df494dee675980849a1a6..6a6434d18d43c22e0612150172a254dac2430d44 100644
--- a/debian/steam-runtime-tools-bin.install
+++ b/debian/steam-runtime-tools-bin.install
@@ -1,4 +1,5 @@
 usr/bin/steam-runtime-check-requirements
 usr/bin/steam-runtime-input-monitor
+usr/bin/steam-runtime-steam-remote
 usr/bin/steam-runtime-system-info
 usr/share/man/man1/steam-runtime-*
diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h
index 6fdf671d7a8d15b51efbdfa214e55f38d1e45311..2234bea638c8e9ba3c29c02c7387c8440e02acab 100644
--- a/steam-runtime-tools/utils-internal.h
+++ b/steam-runtime-tools/utils-internal.h
@@ -109,6 +109,10 @@ G_GNUC_INTERNAL gboolean _srt_str_is_integer (const char *str);
 gboolean _srt_fstatat_is_same_file (int afd, const char *a,
                                     int bfd, const char *b);
 
+G_GNUC_INTERNAL gboolean _srt_steam_command_via_pipe (const char * const *arguments,
+                                                      gssize n_arguments,
+                                                      GError **error);
+
 /*
  * _srt_is_same_stat:
  * @a: a stat buffer
diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c
index b9000c940072d376ab27e463cc162171b90dc5ff..7fe46472a23ed9c6370d8e4cc4d72783e5240867 100644
--- a/steam-runtime-tools/utils.c
+++ b/steam-runtime-tools/utils.c
@@ -1022,3 +1022,78 @@ _srt_fstatat_is_same_file (int afd,
           && fstatat (bfd, b, &b_buffer, AT_EMPTY_PATH) == 0
           && _srt_is_same_stat (&a_buffer, &b_buffer));
 }
+
+/*
+ * _srt_steam_command_via_pipe:
+ * @arguments: (not nullable) (element-type utf8) (transfer none): An array
+ *  of command-line arguments that need to be passed to the Steam pipe
+ * @n_arguments: Number of elements of @arguments to use, or negative if
+ *  @arguments is %NULL-terminated
+ * @error: Used to raise an error on failure
+ *
+ * If @n_arguments is positive it's the caller's responsibility to ensure that
+ * @arguments has at least @n_arguments elements.
+ * If @n_arguments is negative, @arguments must be %NULL-terminated.
+ *
+ * Returns: %TRUE if the provided @arguments were successfully passed to the
+ *  running Steam client instance
+ */
+gboolean
+_srt_steam_command_via_pipe (const char * const *arguments,
+                             gssize n_arguments,
+                             GError **error)
+{
+  glnx_autofd int fd = -1;
+  int ofd_flags;
+  g_autofree gchar *steampipe = NULL;
+  g_autoptr(GString) args_string = g_string_new ("");
+  gsize length;
+  gsize i;
+
+  g_return_val_if_fail (arguments != NULL, FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  if (n_arguments >= 0)
+    length = n_arguments;
+  else
+    length = g_strv_length ((gchar **) arguments);
+
+  steampipe = g_build_filename (g_get_home_dir (), ".steam", "steam.pipe", NULL);
+
+  fd = open (steampipe, O_WRONLY | O_NONBLOCK | O_CLOEXEC | O_NOCTTY);
+
+  if (fd < 0 && (errno == ENOENT || errno == ENXIO))
+    return glnx_throw_errno_prefix (error, "Steam is not running");
+  else if (fd < 0)
+    return glnx_throw_errno_prefix (error, "An error occurred trying to open the Steam pipe");
+
+  ofd_flags = fcntl (fd, F_GETFL, 0);
+
+  /* Remove O_NONBLOCK to block if we write more than the pipe-buffer space */
+  if (fcntl (fd, F_SETFL, ofd_flags & ~O_NONBLOCK) != 0)
+    return glnx_throw_errno_prefix (error, "Unable to set flags on the steam pipe fd");
+
+  /* We hardcode the canonical steam installation path, instead of actually
+   * searching where Steam has been installed, because apparently this
+   * information is not used for anything in particular and Steam just
+   * discards it */
+  g_string_append (args_string, "'~/.steam/root/ubuntu12_32/steam'");
+
+  for (i = 0; i < length; i++)
+    {
+      g_autofree gchar *quoted = NULL;
+
+      quoted = g_shell_quote (arguments[i]);
+
+      g_string_append (args_string, " ");
+      g_string_append (args_string, quoted);
+    }
+
+  g_string_append (args_string, "\n");
+
+  if (glnx_loop_write (fd, args_string->str, args_string->len) < 0)
+    return glnx_throw_errno_prefix (error,
+                                    "An error occurred trying to write to the Steam pipe");
+
+  return TRUE;
+}