Skip to content
Snippets Groups Projects

Steam compatibility tool interface

Compatibility tool declaration

Compatibility tools are declared by a file compatibilitytool.vdf, which is a VDF text file in this format:

"compatibilitytools"
{
  "compat tools"
  {
    "my_compat_tool"
    {
      "install_path" "."
      "display_name" "My Compatibility Tool"
      "from_oslist" "windows"
      "to_oslist" "linux"
    }
  }
}

compat tools can presumably contain one or more compatibility tools, each identified by a unique name, in this case my_compat_tool.

Each compatibility tool can have these fields:

install_path
Installation directory containing toolmanifest.vdf and other necessary files, for example /path/to/steamapps/common/Proton - Experimental for Proton
display_name
Name to display in the Steam user interface
from_oslist
Operating system(s?) whose executables can be run by this compatibility tool, for example windows for Proton
to_oslist
Operating system(s?) that can run this compatibility tool, for example linux for Proton

For the compatibility tools provided by Steam itself, such as Steam Linux Runtime and Proton, the equivalent of this information is downloaded out-of-band and stored in ~/.steam/root/appcache/appinfo.vdf, so the depot downloaded into the Steam library will not contain this file.

Third-party compatibility tools can be installed in various locations such as ~/.steam/root/compatibilitytools.d.

Each subdirectory of compatibilitytools.d that contains compatibilitytool.vdf is assumed to be a compatibility tool. The installation path should be "." in this case.

Alternatively, the manifest can be placed directly in compatibilitytools.d with the install_path set to the relative or absolute path to the tool's installation directory.

Tool manifest

Each compatibility tool has a tool manifest, toolmanifest.vdf, which is a VDF text file with one top-level entry, manifest.

manifest has the following known fields:

version
The version number of the file format. The current version is 2. The default is 1.
commandline
The command-line for the entry point.
require_tool_appid
If set, this compatibility tool needs to be wrapped in another compatibility tool, specified by its numeric Steam app ID. For example, Proton 5.13 needs to be wrapped by "Steam Linux Runtime - soldier", so it sets this field to 1391110.
unlisted
If 1, this compatibility tool will not be shown to users as an option for running games. For example, until Steam is able to distinguish between Steam Runtime 1 'scout' and Steam Runtime 2 'soldier' as distinct platforms, it is not useful to run ordinary Steam games under 'soldier', due to it being incompatible with 'scout'.
use_sessions
If set to 1, older versions of Steam would use the "session mode" described below.
use_tool_subprocess_reaper
If set to 1, Steam will send SIGINT to the compatibility tool instead of proceeding directly to SIGKILL, to give it a chance to do graceful cleanup.

Command-line

In a version 1 manifest, the commandline is a shell expression. The first word should start with / and is interpreted as being relative to the directory containing the compat tool, so /run really means something like ~/.local/share/Steam/steamapps/common/MyCompatTool/run.

The game's command-line will be appended to the tool's command-line, so if you are using getopt or a compatible command-line parser, you might want to use a commandline like /run --option --other-option -- to get the game's command-line to appear after a -- separator.

In a version 2 manifest, the special token %verb% can appear in the commandline. It is replaced by either run or waitforexitandrun.

If a compatibility tool has require_tool_appid set, then the command-line is built up by taking the required tool, then appending the tool that requires it, and finally appending the actual game: so if a compat tool named Inner requires a compat tool named Outer, and both tools have /run %verb% -- as their commandline, then the final command line will look something like this:

/path/to/Outer/run waitforexitandrun -- \
/path/to/Inner/run waitforexitandrun -- \
/path/to/game.exe

(In reality it would all be one line, rather than having escaped newlines as shown here.)

Launch options

If a Steam game has user-specified launch options configured in its Properties, and they contain the special token %command%, then %command% is replaced by the entire command-line built up from the compatibility tools. For example, if a compat tool named Inner requires a compat tool named Outer, both tools have /run %verb% -- as their commandline, and the user has set the Launch Options in the game's properties to

DEBUG=yes taskset --cpu-list 0,2 %command% -console

then the final command line will look something like this:

DEBUG=yes taskset --cpu-list 0,2 \
/path/to/Outer/run waitforexitandrun -- \
/path/to/Inner/run waitforexitandrun -- \
/path/to/game.exe -console

(In reality it would all be one line, rather than having escaped newlines as shown here.)

If the user-specified launch options for a Steam game do not contain %command%, then they are simply appended to the command-line. For example, setting the launch options to --debug is equivalent to %command% --debug.

Shortcuts for non-Steam games do not currently implement the special handling for %command%: the configured launch options are simply appended to the command-line, regardless of whether they contain %command% or not.

Please note that not all invocations of compatibility tools take the user-specified launch options into account: they are used when running the actual game, but they are not used for install scripts.

Environment

Some environment variables are set by Steam, including:

LD_LIBRARY_PATH
Used to load Steam Runtime libraries.
LD_PRELOAD
Used to load the Steam Overlay.
STEAM_COMPAT_APP_ID
The decimal app-ID of the game, for example 440 for Team Fortress 2.
STEAM_COMPAT_CLIENT_INSTALL_PATH
The absolute path to the directory where Steam is installed. This is the same as the target of the ~/.steam/root symbolic link.
STEAM_COMPAT_DATA_PATH
The absolute path to a directory that compatibility tools can use to store game-specific data. For example, Proton puts its WINEPREFIX in $STEAM_COMPAT_DATA_PATH/pfx.
STEAM_COMPAT_INSTALL_PATH
The absolute path to the game's installation directory, for example /home/you/.local/share/Steam/steamapps/common/Estranged Act I, even if the current working directory is a subdirectory of this (as is the case for Estranged: Act I (261820) for example).
STEAM_COMPAT_LIBRARY_PATHS
Colon-delimited list of paths to Steam Library directories containing the game, the compatibility tools if any, and any other resources that the game will need, such as DirectX installers.
STEAM_COMPAT_MOUNTS
Colon-delimited list of paths to additional directories that are to be made available read/write in a pressure-vessel container.
STEAM_COMPAT_SESSION_ID
In the historical session mode (see below), this is used to link together multiple container invocations into a logical "session".
STEAM_COMPAT_SHADER_PATH
The absolute path to the variable data directory used for cached shaders, if any.
STEAM_COMPAT_TOOL_PATHS
Colon-delimited list of paths to Steam compatibility tools in use. Typically this will be a single path, but when using tools with require_tool_appid set, such as Proton, it is a colon-separated list with the "innermost" tool first and the "outermost" tool last.
SteamAppId
The same as STEAM_COMPAT_APP_ID, but only when running the actual game; not set when running install scripts or other setup commands. The Steamworks API assumes that every process with this environment variable set is part of the actual game.

When Steam invokes a tool with require_tool_appid set, such as Proton, the environment variables are set as described for the "outermost" tool, which can change them if required before it invokes the "innermost" tool (although most should not be changed).

For example, when using Proton with "Steam Linux Runtime - soldier", the "outer" compatibility tool "Steam Linux Runtime - soldier" is run with LD_LIBRARY_PATH set by the Steam Runtime to point to mixed host and scout libraries. After setting up the container, it runs the "inner" compatibility tool (Proton) with an entirely new LD_LIBRARY_PATH pointing to mixed host and soldier libraries.

Native Linux Steam games

This is the simplest situation and can be considered to be the baseline.

In recent versions of Steam, the game process is wrapped in a reaper process which sets itself as a subreaper using PR_SET_CHILD_SUBREAPER (see prctl(2) for details).

Version 1 compat tools are not invoked specially.

Version 2 compat tools are invoked with a %verb% in the commandline (if any) replaced by waitforexitandrun.

The game is expected to run in the usual way. Conventionally, it does not double-fork to put itself in the background, but if it does, any background processes will be reparented to have the subreaper as their parent.

The current working directory is the working directory configured in the game's Steam metadata (for example estrangedact1 for Estranged: Act 1, 261820), or the game's directory (or maybe the executable's directory?) if unconfigured. The compatibility tool is expected to preserve this working directory when running the actual game.

The environment variable STEAM_COMPAT_SESSION_ID is not set.

The environment variable STEAM_COMPAT_APP_ID is set to the app-ID of the game. The environment variable SteamAppId has the same value.

The launch options are used.

Windows games with no install script

Some Windows games, such as Soldat (638490), do not have an "install script" in their metadata. Running these games behaves much the same as a native Linux game: it is wrapped in a subreaper, version 1 compat tools are not invoked specially, and version 2 compat tools are invoked with a %verb% in the commandline (if any) replaced by waitforexitandrun.

The environment variable STEAM_COMPAT_SESSION_ID is not set. Historically, it was set to a unique token that was not used in any previous invocation.

The environment variable STEAM_COMPAT_APP_ID is set to the app-ID of the game. The environment variable SteamAppId has the same value.

The current working directory is the working directory configured in the game's Steam metadata, as usual.

The launch options are used.

Windows games with an install script (since Steam beta 1623823138)

Other Windows games, such as Everquest (205710), have an install script, conventionally named installscript.vdf, which must be run by an interpreter.

Since Steam beta 1623823138, these games are run like this:

  • Run the install script. For version 1 compat tools, the compat tool is run as usual, except that the command appended to the command-line is the install script interpreter, not the actual game. For version 2 compat tools, the %verb% is set to run instead of the usual waitforexitandrun.

    The environment variable STEAM_COMPAT_SESSION_ID is not set.

    The environment variable STEAM_COMPAT_APP_ID is set to the app-ID of the game.

    The environment variable SteamAppId is not set in this case.

    The current working directory is not the game's directory in this case. As currently implemented, it appears to be the Steam installation (usually ~/.local/share/Steam or ~/.steam/debian-installation) but this is probably not guaranteed.

    The launch options are not used here.

  • Run the actual game in the usual way.

    The environment variable STEAM_COMPAT_SESSION_ID is not set.

    The environment variables STEAM_COMPAT_APP_ID and SteamAppId are both set to the app-ID of the game as usual.

    The current working directory is the working directory configured in the game's Steam metadata, as usual.

    The launch options are used, as usual.

Historical behaviour of Windows games (session mode v2)

Before Steam beta 1623823138, each Windows game had several setup commands to run before it could be launched. They were invoked like this:

  • Run the first setup command. For version 1 compat tools, the compat tool is run as usual, except that the command appended to the command-line is the setup command, not the actual game. For version 2 compat tools, additionally the %verb% is set to run instead of waitforexitandrun.

    The environment variable STEAM_COMPAT_SESSION_ID is set to a unique token (in practice a 64-bit number encoded in hex).

    The environment variable STEAM_COMPAT_APP_ID is set to the app-ID of the game.

    The environment variable SteamAppId is not set in this case.

    The current working directory is not the game's directory in this case. As currently implemented, it appears to be the Steam installation (usually ~/.local/share/Steam or ~/.steam/debian-installation) but this is probably not guaranteed.

    The launch options are not used here.

    The compat tool is expected to do any setup that it needs to do (for example pressure-vessel must start a container), then run the given command and exit. The compat tool may leave processes running in the background.

  • Run the second setup command, in the same way as the first, and so on. More than one command can be run in parallel, so tools that need to do setup (such as pressure-vessel) must use a lock to ensure the setup is only done by whichever setup command wins the race to be the first.

    All environment variables are the same as for the first setup command, and in particular the STEAM_COMPAT_SESSION_ID is the same. This is how compatibility tools can know which containers or subprocesses to reuse.

  • When all setup commands have finished, run the actual game. For version 2 compat tools, the %verb% is set to waitforexitandrun. The compat tool is expected to terminate any background processes (for example pressure-vessel terminates the container and Proton terminates the wineserver) and wait for them to exit, then launch the actual game.

    The environment variable STEAM_COMPAT_SESSION_ID is set to the same unique token as for all the setup commands, so that the compat tool can identify which subprocesses or containers to tear down.

    The environment variables STEAM_COMPAT_APP_ID and SteamAppId are both set to the app-ID of the game as usual.

    The launch options are used, as usual.

Non-Steam games

Version 1 compat tools are not invoked specially.

Version 2 compat tools are invoked with a %verb% in the commandline (if any) replaced by waitforexitandrun.

The environment variable STEAM_COMPAT_SESSION_ID is not set. Historically, it was set to a unique token that was not used in any previous invocation.

STEAM_COMPAT_APP_ID is set to 0. SteamAppId is not set.

STEAM_COMPAT_DATA_PATH is set to a unique directory per non-Steam game. It is currently in the same format as Steam games' equivalent directories, but with a large arbitrary integer replacing the Steam app ID.

STEAM_COMPAT_INSTALL_PATH is not set.

LD_LIBRARY_PATH is usually set to the empty string to "escape" from the Steam Runtime library stack for non-Steam games, although games configured in Steam via development tools can be flagged to use the Steam Runtime library stack (this is done for games that are intended to be released onto Steam as native Linux games).

The current working directory defaults to the directory containing the main executable, but can be reconfigured through the shortcut's properties. Steam Linux Runtime (pressure-vessel) containers will not work as expected unless this is set to the game's top-level directory.

Launch options are appended to the command-line. The special token %command% in Steam games' launch options is not used here.