cloud-svc was a worse re-implementation of what restic-rest-server already does (--private-repos + --append-only + native retention + chunk-level dedup). Pivoting before either ships in production. cloud-sync.jar becomes a restic CLI wrapper. ~200 LOC instead of ~2000+ in the custom-server path. Server-side prune via operator master password (option 1 — multi-key per repo). Open questions flagged at end of doc for confirmation.
cloud-sync
Single-jar Kotlin client for cloud-svc. Drops into Prism / MMC / ATLauncher / frazclient pre-launch + post-exit hooks alongside packwiz-installer-bootstrap. One tool, all launchers, no Python dependency on the client side.
Status
Skeleton. Build works, jar runs, CLI parses subcommands. Real sync logic + conflict UI land in subsequent commits. See DESIGN.md in cloud-svc for the underlying contract this jar implements.
Usage (planned)
In Prism's instance settings → Custom commands:
Pre-launch command:
"$INST_JAVA" -jar /path/to/cloud-sync.jar pull \
--url=https://cloud.timemachine.center \
--pack-folder=$INST_MC_DIR
Post-exit command:
"$INST_JAVA" -jar /path/to/cloud-sync.jar push \
--url=https://cloud.timemachine.center \
--pack-folder=$INST_MC_DIR
Token comes from $INST_MC_DIR/.cloud-token (paste once from your Discord-bot DM), --token <STR>, or CLOUD_TOKEN env.
CLI
java -jar cloud-sync.jar <subcommand> [flags]
Subcommands:
pull Fetch user's cloud state, apply conflict resolution, write to instance.
push Walk instance, build snapshot, upload changed files.
Flags:
--url <URL> cloud-svc base URL (required)
--pack-folder <DIR> instance dir to sync into/from (default: ".")
--token <STR> bearer token (or use --token-file)
--token-file <PATH> read token from this file (default: <pack-folder>/.cloud-token)
-g, --no-gui headless mode; conflicts auto-resolve to remote-wins
-V, --version print version
-h, --help print this help
Build
Requires JDK 17–21 (JDK 26 currently breaks Kotlin 2.1's compiler). Easiest: containerized via podman/docker.
podman run --rm -v "$PWD":/work:Z -w /work docker.io/gradle:8.10.2-jdk21 \
gradle --no-daemon shadowJar
Output: build/libs/cloud-sync-<version>.jar. Single fat jar; ship as-is.
For local development with a matching JDK installed:
./gradlew shadowJar
UI
Swing + FlatLaf (FlatMacDarkLaf theme). Closest visual match to Prism's Qt look in pure Java. Falls back to system look-and-feel if FlatLaf init fails (e.g., on bare-bones X servers).
Conflict resolution dialog: per-file [keep local | use remote | skip] radio buttons + "use all local/remote" + Cancel/Continue. Headless mode (-g) defaults all conflicts to remote-wins (Steam's default).
Where this fits in the automc stack
| Tool | What it owns |
|---|---|
| packwiz-installer-bootstrap | Mod sync — jars, configs shipped by the modpack, options.txt baseline |
| cloud-sync (this) | Per-user sync — player-modified configs, JourneyMap waypoints, screenshots |
| frazclient | Cracked-launcher orchestration — JDK, vanilla MC, Fabric, then invokes both jars |
cloud-sync and packwiz-installer-bootstrap are deliberately separate jars so players can disable cloud sync without affecting modpack sync (or vice versa) by just commenting out the line in Prism's hook config.
License
MIT.