Skip to content

ruffsl/CtrlAssist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

15 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Banner

CtrlAssist brings "controller assist" functionality to Linux gaming by allowing multiple physical controllers to operate as a single virtual input device. This enables collaborative play and customizable gamepad setups, making it easier for players of all ages and abilities to enjoy games together. While similar features exist on modern game consoles, CtrlAssist is an open source project that enhances accessibility for PC gaming, offering additional quality-of-life improvements through virtual input devices on Linux.

CI Pipeline Crates.io Version Crates.io Dependencies Crates.io MSRV Crates.io Total Downloads Crates.io License

โœจ Features

  • ๐ŸŽฎ Combine physical controllers into one virtual gamepad
    • Controllers are assigned as either Primary or Assist
  • ๐ŸŽ›๏ธ Customizable multiplexing modes for buttons and axes
    • Logically merging or preempting events is flexible
  • ๐Ÿ™ˆ Hide physical controllers for improved game compatibility
    • Multiple hiding strategies for avoiding interference
  • ๐Ÿ•น๏ธ Spoof gamepad vendor for in-game layout recognition
    • Mimic either Primary or Assist controller hardware
  • ๐Ÿซจ Rumble pass-through from virtual to physical devices
    • Forward force feedback to either or both controllers
  • ๐Ÿ–ฑ๏ธ System tray interface for graphical desktop environments
    • Configure controllers and mux options via the taskbar
    • Start/stop muxing with live status feedback
    • Desktop notifications for status changes
    • Persistent user settings across restarts

System Tray Screenshot

๐ŸŽ›๏ธ Modes

  • ๐Ÿ‘‘ Priority (default): Assist controller overrides when active
    • Axes: Prioritize Assist when active (exceeds deadzone)
      • Buttons: Prioritize Assist when button released
      • Triggers: Prioritize largest value from either
    • Ideal for partial and asynchronous assistance
      • E.g. Assist for movement while Primary for actions
  • โš–๏ธ Average: Blend weighted inputs from both controllers
    • Axes: Averaged when both are active (exceed deadzone)
      • Buttons: logically OR'ed between pressed controllers
      • Triggers: Averaged when both are active (exceed deadzone)
    • Ideal for cooperative input and subtle corrections
      • E.g. For counter steer/brake assist in racing games
  • ๐Ÿ”„ Toggle: Switch Active controller on demand
    • All inputs forwarded from currently active controller
      • Toggle Active controller via the Mode button on Assist
      • Immediately synchronizes input to current Active state
    • Ideal when fine-grain conflict-free control is needed
      • E.g. Game menu navigation or precise interventions

โฌ‡๏ธ Install

The following installation methods are available:

  • ๐Ÿฆ€ Cargo (Rust package manager)
    • Ideal for customization and unsandboxed use
    • Suitable for development and contributing
    • E.g. fork custom features and upstream fixes
  • ๐Ÿ“ฆ Flatpak (Linux application sandbox)
    • Ideal for easy install on SteamOS, Bazzite, etc.
    • Suitable for immutable Linux distributions
    • E.g. where installing build tools is a hassle

๐Ÿฆ€ Cargo

Add the --force flag to upgrade to latest version:

cargo install ctrlassist

๐Ÿ“ฆ Flatpak

  • Runtime dependencies
    • Flatpak (likely already installed)

Download latest bundle from releases page and install:

export VERSION=v0.2.0
wget https://github.com/ruffsl/ctrlassist/releases/download/$VERSION/ctrlassist.flatpak
flatpak install --user ctrlassist.flatpak

Run and test via Flatpak using the application ID:

flatpak run io.github.ruffsl.ctrlassist --help

Or launch as system tray via installed desktop icon.

๐Ÿ“– Usage

Use the --help flag for information on each CLI subcommand:

$ ctrlassist --help
Multiplex multiple controllers into virtual gamepad

Usage: ctrlassist <COMMAND>

Commands:
  list  List all detected controllers and respective IDs
  mux   Multiplex connected controllers into virtual gamepad
  tray  Launch system tray app for graphical control
  help  Print this message or the help of the given subcommand(s)

Options:
  -h, --help     Print help
  -V, --version  Print version

๐Ÿ–ฑ๏ธ tray

Launch the system tray app for graphical control:

$ ctrlassist tray
CtrlAssist system tray started
Configure and control the mux from your system tray
Press Ctrl+C to exit

The system tray provides:

  • Controller selection menus for Primary and Assist
  • Configuration options for mux mode, hiding, spoofing, and rumble
  • Start/Stop buttons with visual feedback
  • Live status indicator in the tray icon
  • Desktop notifications for status changes
  • Persistent settings saved to ~/.config/ctrlassist/config.toml

Options are greyed out while the mux is running but show current active selections.

๐Ÿงพ list

List all detected controllers and respective IDs:

$ ctrlassist list
(0) Microsoft Xbox One
(1) PS4 Controller

๐Ÿ”€ mux

Multiplex first two detected controllers by default:

$ ctrlassist mux
Primary: (0) Microsoft Xbox One
Assist:  (1) PS4 Controller
...
Mux Active. Press Ctrl+C to exit.

๐ŸŽฎ Primary Assist Mapping

Manually specify Primary and Assist controllers via IDs:

$ ctrlassist mux --primary 1 --assist 0
Primary: (1) PS4 Controller
Assist:  (0) Microsoft Xbox One
...

๐ŸŽ›๏ธ Mux Mode Selection

Manually specify mode for merging controllers:

$ ctrlassist mux --mode priority
...

๐Ÿ•น๏ธ Spoof Virtual Device

Mimic controller hardware for in-game layout recognition:

$ ctrlassist mux --spoof primary
Primary: (0) Microsoft Xbox One
Assist:  (1) PS4 Controller
Virtual: (2) Microsoft X-Box One pad (Firmware 2015)

Warning

Combining spoofing with some hiding strategies may also hide the virtual device.

๐Ÿซจ Rumble Pass-Through

Target force feedback to either or both physical controllers:

$ ctrlassist mux --rumble both
...

๐Ÿ™ˆ Hide Physical Devices

There are multiple hiding strategies to avoid input conflicts:

Strategy Access/Compatibility Granularity Restart Required
Steam No root, Flatpak compatible Vendor/Product ID Steam only
System Root required, no Flatpak Per-device Game/Launcher

For example, use Steam when running CtrlAssist via Flatpak. For 2v1 scenarios, where the third player not using CtrlAssist shares the same controller make and model, use System to avoid hiding the third player's gamepad.

Steam Input

Automatically configure Steam's controller blacklist:

$ ctrlassist mux --hide steam
...

Note

Restart Steam for blacklist to take effect; CtrlAssist reverts config on exit.

Warning

Combining this hiding strategy with spoofing may also hide the virtual device.

System Level

Restrict device tree permissions system-wide:

$ sudo ctrlassist mux --hide system
...

Note

Restart game/launcher to force rediscovery; CtrlAssist reverts change on exit.

Important

Not possible via Flatpak sandbox for security. Use --hide steam instead.

โš™๏ธ Configuration

The system tray saves settings to $XDG_CONFIG_HOME/ctrlassist/config.toml:

# Last selected controllers (by name for best-effort matching)
primary_name = "Microsoft Xbox One"
assist_name = "PS4 Controller"

# Mux configuration
mode = "Priority"
hide = "Steam"
spoof = "None"
rumble = "Both"

Settings are loaded on startup and saved when starting the mux. Controllers are matched by name (best-effort) if IDs change between sessions.

๐Ÿ•ณ๏ธ Limitations

  • System hiding requires root access
    • temporarily modifies group permissions for selected devices
  • Hiding must be done before starting games or launchers
    • processes with open file handles may retain device access
  • Reconnecting a hidden controller may revert its visibility
    • Steam hiding persists across reconnects while CtrlAssist is running
    • System hiding: custom udev rules needed for persistent permissions
  • Steam hiding affects all controllers of the same make and model
    • blacklists by vendor/product ID, not individual devices
  • Steam hiding requires Steam restart
    • Steam only checks controller_blacklist config on startup
  • Toggle mode requires pressing all buttons and axes after startup
    • gilrs lazily initializes gamepad state used for synchronization

๐Ÿ“š Background