Skip to content

Conversation

@S1M0N38
Copy link
Collaborator

@S1M0N38 S1M0N38 commented Jan 1, 2026

Summary

Implements Linux platform support for BalatroBot using Steam's Proton compatibility layer.

Closes #128

Changes

Configuration

  • Add steam_path field to Config dataclass
  • Add --steam-path CLI argument
  • Add BALATROBOT_STEAM_PATH environment variable

Linux Launcher (src/balatrobot/platforms/linux.py)

  • New LinuxLauncher class for running Balatro through Proton
  • Auto-detect Steam installation from known paths:
    • ~/.local/share/Steam (standard)
    • ~/.steam/steam (symlink)
    • ~/snap/steam/common/.local/share/Steam (Snap)
    • ~/.var/app/com.valvesoftware.Steam/.local/share/Steam (Flatpak)
  • Auto-detect Proton runtime (prefers Experimental, falls back to latest versioned)
  • Configure required Proton environment variables:
    • STEAM_COMPAT_CLIENT_INSTALL_PATH
    • STEAM_COMPAT_DATA_PATH
    • WINEDLLOVERRIDES="version=n,b" for lovely injection

Tests

  • Add TestLinuxLauncher with Linux-only tests (@pytest.mark.skipif)
  • Test path validation, environment building, and command construction

Usage

# Auto-detect Steam installation
balatrobot --platform linux

# Explicit Steam path
balatrobot --platform linux --steam-path ~/.local/share/Steam

# Via environment variable
BALATROBOT_STEAM_PATH=~/.local/share/Steam balatrobot --platform linux

Requirements

  • Linux with Steam and Proton installed
  • Balatro installed via Steam
  • Lovely injector (version.dll) in Balatro directory
  • Run Balatro once through Steam to create Proton prefix

Add steam_path field to Config dataclass and --steam-path CLI argument
for specifying Steam installation path on Linux systems.

- Add BALATROBOT_STEAM_PATH environment variable mapping
- Add --steam-path CLI flag with help text
Add LinuxLauncher class for running Balatro through Steam's Proton
compatibility layer on Linux systems.

Features:
- Auto-detect Steam installation from known paths:
  - ~/.local/share/Steam (standard)
  - ~/.steam/steam (symlink)
  - ~/snap/steam/common/.local/share/Steam (Snap)
  - ~/.var/app/com.valvesoftware.Steam/.local/share/Steam (Flatpak)
- Auto-detect Proton runtime (Experimental or latest versioned)
- Set required Proton environment variables:
  - STEAM_COMPAT_CLIENT_INSTALL_PATH
  - STEAM_COMPAT_DATA_PATH
  - WINEDLLOVERRIDES for lovely injection
- Launch via: proton run Balatro.exe

Closes #128
Update get_launcher() to return LinuxLauncher for 'linux' platform
instead of raising NotImplementedError.
- Add TestLinuxLauncher class with Linux-only tests
- Test validate_paths error cases (missing/invalid Steam dir)
- Test build_env includes Proton environment variables
- Test build_cmd returns correct proton run command
- Update test_linux_not_implemented to test_linux_returns_linux_launcher
Copilot AI review requested due to automatic review settings January 1, 2026 13:53
@S1M0N38
Copy link
Collaborator Author

S1M0N38 commented Jan 1, 2026

Hey @stirby 👋

Since you have Balatro installed with Proton on Linux, would you mind testing this PR?

Quick Test Instructions

# Checkout the PR
gh pr checkout 134

# Install dependencies and run all checks
make all

# Run platform tests specifically (Linux-only tests will run on your machine)
pytest tests/cli/test_platforms.py -v

# Run just the new Linux launcher tests
pytest tests/cli/test_platforms.py::TestLinuxLauncher -v

Manual Testing

# Test auto-detection (should find your Steam installation)
balatrobot --platform linux --debug

# Or specify Steam path explicitly
balatrobot --platform linux --steam-path ~/.local/share/Steam --debug

What to verify

  1. Steam path auto-detection works for your setup
  2. Proton runtime is detected correctly
  3. Balatro launches and the API becomes healthy
  4. The mod injects properly (lovely's version.dll)

Let me know if you hit any issues! 🎴

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements Linux platform support for BalatroBot by adding a new launcher that uses Steam's Proton compatibility layer to run the Windows version of Balatro on Linux. The implementation includes automatic detection of Steam installation paths, Proton runtimes, and game files, with comprehensive configuration options via CLI arguments and environment variables.

Key Changes:

  • Added LinuxLauncher class with auto-detection for Steam, Proton, and Balatro paths
  • Extended configuration system with steam_path field and BALATROBOT_STEAM_PATH environment variable
  • Implemented Proton environment setup with Wine DLL overrides for lovely injector support

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/balatrobot/platforms/linux.py New launcher implementation with Steam/Proton detection and validation logic
src/balatrobot/platforms/__init__.py Updated platform factory to return LinuxLauncher for Linux platform
src/balatrobot/config.py Added steam_path field to Config dataclass and environment variable mapping
src/balatrobot/cli.py Added --steam-path CLI argument for specifying Steam installation path
tests/cli/test_platforms.py Added basic test coverage for LinuxLauncher validation and command building

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 45 to 51
# Find versioned Proton installations (e.g., "Proton 9.0", "Proton 8.0")
proton_dirs = []
for entry in common.iterdir():
if entry.is_dir() and entry.name.startswith("Proton "):
match = re.match(r"Proton (\d+(?:\.\d+)?)", entry.name)
if match:
version = float(match.group(1))
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converting version strings to float for comparison can lead to incorrect sorting for versions with multiple decimal points. For example, "Proton 8.0.5" would be captured as "8.0" and converted to 8.0, while "Proton 8.1" would be 8.1. However, the regex r"Proton (\d+(?:\.\d+)?)" only captures one optional decimal component, so this limitation is consistent. Consider documenting this limitation or using a more robust version comparison approach if multi-decimal versions are expected in the future.

Suggested change
# Find versioned Proton installations (e.g., "Proton 9.0", "Proton 8.0")
proton_dirs = []
for entry in common.iterdir():
if entry.is_dir() and entry.name.startswith("Proton "):
match = re.match(r"Proton (\d+(?:\.\d+)?)", entry.name)
if match:
version = float(match.group(1))
# Find versioned Proton installations (e.g., "Proton 9.0", "Proton 8.0", "Proton 8.0.5")
proton_dirs = []
for entry in common.iterdir():
if entry.is_dir() and entry.name.startswith("Proton "):
# Capture one or more dot-separated numeric components after "Proton "
match = re.match(r"Proton (\d+(?:\.\d+)*)", entry.name)
if match:
version_str = match.group(1)
# Parse version into a tuple of integers for correct numeric sorting
version = tuple(int(part) for part in version_str.split("."))

Copilot uses AI. Check for mistakes.
Comment on lines +182 to +227
@pytest.mark.skipif(not IS_LINUX, reason="Linux only")
class TestLinuxLauncher:
"""Tests for LinuxLauncher (Linux only)."""

def test_validate_paths_missing_steam(self, tmp_path):
"""Raises RuntimeError when Steam installation not found."""
launcher = LinuxLauncher()
config = Config(steam_path=str(tmp_path / "nonexistent"))

with pytest.raises(RuntimeError, match="Steam directory not found"):
launcher.validate_paths(config)

def test_validate_paths_invalid_steam(self, tmp_path):
"""Raises RuntimeError when Steam directory has no steamapps."""
# Create a fake Steam directory without steamapps
steam_path = tmp_path / "Steam"
steam_path.mkdir()

launcher = LinuxLauncher()
config = Config(steam_path=str(steam_path))

with pytest.raises(RuntimeError, match="Invalid Steam directory"):
launcher.validate_paths(config)

def test_build_env_includes_proton_vars(self, tmp_path):
"""build_env includes Proton compatibility environment variables."""
launcher = LinuxLauncher()
config = Config(steam_path="/path/to/Steam")

env = launcher.build_env(config)

assert env["STEAM_COMPAT_CLIENT_INSTALL_PATH"] == "/path/to/Steam"
assert "compatdata/2379780" in env["STEAM_COMPAT_DATA_PATH"]
assert env["WINEDLLOVERRIDES"] == "version=n,b"

def test_build_cmd(self, tmp_path):
"""build_cmd returns proton run command."""
launcher = LinuxLauncher()
config = Config(
balatro_path="/path/to/proton",
love_path="/path/to/Balatro.exe",
)

cmd = launcher.build_cmd(config)

assert cmd == ["/path/to/proton", "run", "/path/to/Balatro.exe"]
Copy link

Copilot AI Jan 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test coverage for LinuxLauncher is incomplete compared to other platform launchers. Consider adding tests for:

  • Missing Balatro.exe (similar to test_validate_paths_missing_balatro_exe in WindowsLauncher)
  • Missing version.dll (similar to test_validate_paths_missing_version_dll in WindowsLauncher)
  • Missing Proton runtime
  • Missing Proton prefix (compatdata directory)
  • Platform check validation (testing the RuntimeError when not on Linux)

Copilot uses AI. Check for mistakes.
- Add --steam-path option to CLI options table
- Add 'Linux Platform (Proton)' section with:
  - Auto-detected paths (Steam, Balatro.exe, version.dll, Proton)
  - Requirements (Steam, Proton, Lovely, Proton prefix)
  - Launch examples
Use tuple instead of float for semantic version comparison to correctly
handle multi-decimal versions like 'Proton 8.0.5'.

- Change regex from \d+(?:\.\d+)? to \d+(?:\.\d+)* to capture all parts
- Parse version as tuple: '8.10' -> (8, 10) for correct comparison
- Fixes: (8, 10) > (8, 9) vs incorrect float 8.10 < 8.9
Add test_validate_paths_missing_proton_prefix to verify LinuxLauncher
raises RuntimeError when compatdata directory doesn't exist.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(balatrobot): CLI support for Linux through Proton

2 participants