Skip to main content

pyludusavi

PyPI version CI Python versions License: MIT

A robust, type-safe Python wrapper for the Ludusavi CLI.

Features

  • Broad CLI Coverage: Supports the core Ludusavi subcommands and commonly used flags.
  • Linux-First: Native support for both local binaries and Flatpak.
  • Type-Safe: Comprehensive TypedDict models for all JSON outputs (Python 3.12+).
  • Dual-Mode Execution: Transparently handles binary vs. Flatpak command prefixing.
  • TDD-Backed: High-quality implementation with an extensive regression suite.

Setup

For local development, use the project wrapper so virtual environments and tool caches stay outside Dropbox:

source .envrc
./run.sh uv sync

Run validation through the same wrapper:

./run.sh uv run ruff check .
./run.sh uv run ty check src/
./run.sh uv run pytest

Installation

Use uv when adding the package to another Python project:

uv add pyludusavi

Quick Start

Basic Initialization

The wrapper automatically discovers Ludusavi via PATH or Flatpak.

from pyludusavi import Ludusavi

lud = Ludusavi()
print(f"Ludusavi version: {lud.version()}")

Backing Up Games

Perform a preview scan or a full backup.

# Preview a backup for a specific game
result = lud.backup(games=["The Witcher 3"], preview=True)

# Access typed data
for name, game in result.data["games"].items():
    print(f"Game: {name}, Status: {game['change']}")

Searching for Games

Use Steam IDs or fuzzy matching to find games in the manifest.

# Find by Steam ID
result = lud.find(steam_id="292030")

# Use fuzzy matching
result = lud.find(games=["Witcher"], fuzzy=True)

Advanced Usage

Flatpak Support

If you have Ludusavi installed via Flatpak, pyludusavi detects it automatically. You can also specify a custom binary path or Flatpak ID:

lud = Ludusavi(explicit_path="/usr/bin/ludusavi")
lud = Ludusavi(flatpak_id="com.github.mtkennerly.ludusavi")

Custom Config Directory

lud = Ludusavi(config_dir="/home/user/my-ludusavi-config")

Custom Environment

Pass environment overrides when Ludusavi needs a different PATH, HOME, or launcher-specific variable. Overrides are merged onto the current process environment and used for both discovery and command execution.

lud = Ludusavi(env={"PATH": "/opt/ludusavi/bin:/usr/bin", "HOME": "/home/deck"})

Bulk API

For performance-critical bulk operations, use the native api subcommand:

payload = {
    "requests": [
        {"kind": "backup", "games": ["Game 1"]},
        {"kind": "backup", "games": ["Game 2"]}
    ]
}
lud.bulk_api(payload)

Cloud Sync

Use the upload/download helpers with the same common options exposed by the CLI.

lud.cloud_upload(games=["The Witcher 3"], local="/backups", cloud="/cloud", preview=True)
lud.cloud_download(games=["The Witcher 3"], force=True)

Wrap Game Launch

Ludusavi requires either a direct game name or launcher inference when wrapping a command.

lud.wrap(["./game.exe", "--windowed"], name="The Witcher 3")
lud.wrap(["steam", "-applaunch", "292030"], infer="steam", force=True)

Game Aliases

get_game_alias(name) returns the manifest title a custom name is aliased to (or None). Custom games / aliases are created in the Ludusavi GUI or config file; this library reads them but does not write them.

lud.get_game_alias("My Game")  # -> "The Witcher 3" or None

Timeouts

Quick, bounded commands (version, find, config_*, backups_list, schema, complete) default to a 30-second timeout. Long-running operations — backup, restore, wrap, cloud_upload, cloud_download, manifest_update, and bulk_api — default to no timeout (timeout=None) so a long game session or large transfer is not killed. Every one of these accepts an explicit timeout=<seconds> override. A timeout raises LudusaviTimeoutError.

Note: The automatic background probe that verifies the Ludusavi executable during discovery has a fixed, non-configurable 15-second timeout. Timeout expiration rejects the candidate (falling back or raising LudusaviNotFoundError) rather than surfacing a timeout error.

# Wrap a game launch with no time limit (default)
lud.wrap(["./game.exe"], name="The Witcher 3")

# Cap a cloud upload at 5 minutes
lud.cloud_upload(games=["The Witcher 3"], timeout=300)

Reading Logs

Inspect Ludusavi's log directory and current log file:

lud.log_dir()   # -> "/home/user/.config/ludusavi"
lud.log_show()  # -> contents of ludusavi_rCURRENT.log, or "" if it does not exist

Error Handling

  • LudusaviNotFoundError: Raised if the executable or Flatpak isn't found.
  • LudusaviExecutionError: Raised if the process exits with a non-zero code.
  • LudusaviContractError: Raised if the CLI output is malformed or non-JSON when expected.
  • LudusaviTimeoutError: Raised if the process exceeds its timeout. Subclass of LudusaviError, so existing except LudusaviError handlers still catch it.

Dependency Requirements

  • Python 3.12+
  • uv
  • Ludusavi v0.31.0+
  • pytest, pytest-cov, ruff, and ty for local development

License

MIT

Metadata

Release files for pyludusavi 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyludusavi 0.3.0
File Size Uploaded
pyludusavi-0.3.0.tar.gz 12.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyludusavi 0.3.0
File Interpreter ABI Platform
pyludusavi-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 28.0 kB

Release files / pyludusavi-0.3.0.tar.gz

Download URL pyludusavi-0.3.0.tar.gz
Size 12.8 kB
Tags Source
SHA-256 checksum
How to use checksums
f0a0d64f10a5347de11e9c73f027ed06fa0c817be22cd39f5f321a5c1fe896dd
BLAKE2b-256 checksum
How to use checksums
86e2dbc2ddc99abe1a3f604e8202b4bcd5c37d1025cebe8aba8f8bc366467970
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / pyludusavi-0.3.0-py3-none-any.whl

Download URL pyludusavi-0.3.0-py3-none-any.whl
Size 15.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4328381494371cb8cba5c40ee8bfb36641e852d52bb8aaaf7ca66e04fe1104c0
BLAKE2b-256 checksum
How to use checksums
2f5186435530e0de7765749f6713fae2a3ff73c3755529c45ea548d89ca11365
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.11.24 {"installer":{"name":"uv","version":"0.11.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page