Skip to content

Instantly share code, notes, and snippets.

@ntippie
Last active June 16, 2025 00:57
Show Gist options
  • Select an option

  • Save ntippie/3f5523a99d7713e5e237c3b8be909fd2 to your computer and use it in GitHub Desktop.

Select an option

Save ntippie/3f5523a99d7713e5e237c3b8be909fd2 to your computer and use it in GitHub Desktop.
Mac python script to sync Balatro profiles between Steam and iCloud
#!/usr/bin/python3
# adapted from https://github.com/TomJinW/BalatroSave_AppleArcadeMac
import plistlib
from os.path import expanduser, getmtime, join, exists, basename, dirname, isfile
from datetime import datetime
from os import utime, makedirs, listdir
ICLOUD_PATH = f"~/Library/Containers/com.playstack.balatroarcade/Data/Library/Preferences/com.playstack.balatroarcade.plist"
STEAM_PATH = f"~/Library/Application Support/Balatro/"
PROFILE_MAX = 3
file_names = ["meta", "profile"]
def get_mod_time(path):
try:
return getmtime(expanduser(path))
except OSError:
return 0
def get_sync_actions(steam_files, icloud_file):
icloud_mod_time = get_mod_time(icloud_file)
steam_to_icloud = []
icloud_to_steam = []
latest_steam_mod_time = 0
for file in steam_files:
steam_mod_time = get_mod_time(file)
latest_steam_mod_time = max(latest_steam_mod_time, steam_mod_time)
if steam_mod_time > icloud_mod_time:
steam_to_icloud.append(file)
elif icloud_mod_time > steam_mod_time:
icloud_to_steam.append(file)
return steam_to_icloud, icloud_to_steam, latest_steam_mod_time, icloud_mod_time
if __name__ == "__main__":
profile_list = [f"{profile}" for profile in range(1, PROFILE_MAX + 1)]
possible_steam_files = [
join(STEAM_PATH, profile, f"{file_name}.jkr")
for profile in profile_list
for file_name in file_names
]
steam_files = [f for f in possible_steam_files if isfile(expanduser(f))]
steam_to_icloud, icloud_to_steam, steam_mod_time, icloud_mod_time = (
get_sync_actions(steam_files, ICLOUD_PATH)
)
if steam_to_icloud:
print("πŸ”„ Sync from Steam β†’ iCloud")
with open(expanduser(ICLOUD_PATH), "rb") as file:
plist_data = plistlib.load(file)
for file_name in steam_to_icloud:
base_file_name = basename(file_name)
file_dir = dirname(file_name)
profile = basename(file_dir)
# sync modified times for files in the profile
dir_files = [
join(file_dir, f) for f in file_names if isfile(join(file_dir, f))
]
for dir_file in dir_files:
utime(expanduser(dir_file), (steam_mod_time, steam_mod_time))
plist_key = f"{profile}__{base_file_name}.data"
with open(expanduser(file_name), "rb") as file:
file_data = file.read()
plist_data[f"{profile}__{base_file_name}.data"] = file_data
with open(expanduser(ICLOUD_PATH), "wb") as file:
plistlib.dump(plist_data, file)
utime(expanduser(ICLOUD_PATH), (steam_mod_time, steam_mod_time))
if icloud_to_steam:
print("πŸ”„ Sync from iCloud β†’ Steam")
with open(expanduser(ICLOUD_PATH), "rb") as file:
plist_data = plistlib.load(file)
for file_name in icloud_to_steam:
base_file_name = basename(file_name)
profile = basename(dirname(file_name))
plist_key = f"{profile}__{base_file_name}.data"
if plist_key not in plist_data:
icloud_to_steam.remove(file_name)
continue
key_data = plist_data[plist_key]
profile_path = dirname(file_name)
if not exists(expanduser(profile_path)):
makedirs(expanduser(profile_path))
with open(expanduser(file_name), "wb") as file:
print(f"Writing {file_name}")
file.write(key_data)
file.close()
utime(expanduser(file_name), (icloud_mod_time, icloud_mod_time))
if not steam_to_icloud and not icloud_to_steam:
print("βœ… All files are already in sync.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment