Add quadrantmc, a CLI for Quadrant, and ship it with the desktop packages - #68
Merged
Merged
Conversation
Builds a host on the desktop app's data folder (or --data-dir), prints results as text or --json through one Report/Output path, renders host progress events on stderr and translates i18n error keys. First commands: versions, news, telemetry, invoke.
settings list/get/set/unset/mc-folder/push/pull. Every config write bumps lastSettingsUpdated like the desktop frontend's configChanged handler, so settings sync still sees CLI edits as newer. Text settings stay text even when the value looks like JSON, and toggling collectUserData sends or withdraws telemetry as Settings.tsx does.
modpack list/show/create/edit/delete/apply/clear/export/updates/identify/ register/share/import/folder. Ports the frontend's modpack ordering, name sanitizing and share-code parsing as tested functions, parses --loader and --source into core types at the clap boundary, and looks mods up per provider through one dispatch module.
The manifest's version label is a date on CurseForge and an opaque id on Modrinth; the decoded file name from the download URL tells the user which build is installed.
mod search/info/deps/owners/install/remove/update/categories. Search ports the search page's provider selection (settings, category locks, open-source, loader support), category merging and result ordering; install ports the install page's modpack/version/loader defaults and remembers explicit choices in lastUsed* like its pickers.
Resource and shader packs don't depend on a mod loader.
content list/copy/delete/folder over the host's content locations, with copy skipping packs the destination already has as the installed-content page does. prism list/plan/apply/detach; while experimentalFeatures is off they say so instead of surfacing the host's refused-request error. Boolean settings are now read through one config helper.
Chooses the OS keyring service the Quadrant ID login is read from, matching the N-API addon's keyring_service_name, so a sandboxed run can be kept away from the desktop app's login.
account login/logout/info/open/register. login ports the account page's OAuth flow: a random state kept in oauthState, a one-shot listener on the first free of 127.0.0.1:4000-4005 that ignores stray requests like the favicon fetch, and a five-minute timeout. The link is always printed, for when no browser opens on its own.
Ports resolveDeepLink with its test cases: curseforge://install, modrinth:// project links (including wrapped website links), quadrantnext:// mod, modpack and login links, and usequadrant.dev share links. Mod links run the same install as mod install, modpack links the same import as modpack import, and login links finish a sign-in only when their state matches the stored oauthState.
notifications list/read/accept/decline/watch. Ports the notification popover's filtering (modpack update notices hidden when turned off or made by the user) and invite parsing (invite id from the message or the resource id, inviter from the message text). watch runs the app's background workers and prints new notifications until Ctrl+C.
sync list/push/pull/members/invite/kick/delete/share. push reports a newer cloud copy with the way out (--force or sync pull) instead of the bare conflict; pull installs the cloud copy under the linked local modpack's name, paired as the apply page pairs them, and records the sync date.
A CLI output path can name a folder that doesn't exist yet, unlike the desktop save dialog.
Subcommand help listed the global flags among its own options.
docs/cli.md covers building, the global options, every command group, deep links, and how to sandbox a run away from the desktop app's data. The README's feature list points at it.
… collectUserData changes
The crate stays quadrant-cli; the binary, its help and the commands its hints and docs print now use quadrantmc.
The post-install hook adds the install folder to HKCU\Environment Path and the post-uninstall hook removes it, so a sidecar installed there is callable from new terminals. user-path.ps1 holds the logic: it reads Path unexpanded, writes it back as REG_EXPAND_SZ, matches entries case-insensitively and ignoring a trailing backslash, and leaves Path alone when it is already in the wanted state, since the updater re-runs the installer.
src-tauri/tauri.cli.conf.json runs scripts/build-cli.ts after the renderer build, which builds quadrantmc for TAURI_ENV_TARGET_TRIPLE and copies it to src-tauri/binaries/ for bundle.externalBin. It also turns on the NSIS PATH hooks. It stays out of tauri.conf.json because tauri-build fails when an externalBin file is missing, which would break cargo test, rust-analyzer and tauri dev. bun run build:tauri, the macOS ad-hoc build, the release workflow and the Validate Desktop shell build merge it in, so deb, rpm, AppImage, NSIS and the macOS app all ship the CLI.
package() copies binaries one by one, so the sidecar the rpm now ships at /usr/bin/quadrantmc needs its own install line.
AppxManifest.xml gains a second, hidden application for quadrantmc.exe with a console app execution alias, so Store installs can run quadrantmc from a terminal. makeappx requires SupportsMultipleInstances for a console alias. msixbuild.ps1 stages quadrantmc.exe next to quadrant_next.exe for each architecture, taking it from src-tauri/binaries first, and fails when it is missing. The Store workflow builds with tauri.cli.conf.json, uploads each architecture's CLI and stages it for the bundle job.
docs/cli.md says where each desktop package puts the CLI and how to call it, and how packaging builds bundle it. AGENTS.md notes that bun run build:tauri includes the CLI and plain tauri build does not.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
quadrantmc, a command-line client that does everything the desktop frontend does, and ships it with the Linux packages, the Windows installer and the Microsoft Store package.The CLI
src-tauri/crates/quadrant-cliis a thin layer overQuadrantHost, likequadrant-napi. It shares the desktop app's data folder and keyring, so settings, modpacks and the Quadrant ID login are the same in both.quadrant-coreandquadrant-hostare unchanged.Commands cover modpacks (create, edit, apply, clear, export, import a share code, updates, identify, register, share), mods and packs (search across both providers, info, deps, owners, install, remove, update), installed resource and shader packs, Prism instances, Quadrant ID sign-in through the same loopback flow as the Account page, notifications, sync, settings, news, telemetry, deep links (
quadrantmc open <link>) and a rawinvokepassthrough. Every command takes--json. The updater and window-only settings are out of scope. Usage is indocs/cli.md.Frontend-only logic is ported as tested pure functions: modpack ordering, search provider choice and result merging, deep-link and share-code parsing, notification filtering, and the
lastSettingsUpdatedbump that settings sync depends on.Where a terminal can't show what the app shows, the CLI behaves more conservatively:
mod installdefaults to the target modpack's version and loader instead of the last-used ones.--yes.modpack updatesfails when some mods couldn't be checked.Packaging
src-tauri/tauri.cli.conf.jsonbuilds the CLI (scripts/build-cli.ts) and bundles it as a sidecar.bun run build:tauri,release.yml,msstore.ymland the Linux shell check invalidate-desktop.ymlpass it with--config. It is not intauri.conf.jsonbecausetauri-buildfails when a sidecar file is missing, which would breakcargo test, rust-analyzer andtauri dev./usr/bin/quadrantmc. The AUR template now installs it too. Flatpak picks it up from the deb (flatpak run --command=quadrantmc dev.mrquantumoff.mcmodpackmanager).quadrantmc.exein the install folder, and hooks insrc-tauri/windows/add that folder to the user PATH and remove it on uninstall. The PATH change is idempotent, because the updater re-runs the installer, and it keeps theREG_EXPAND_SZentries unexpanded.quadrantmc.msixbuild.ps1andmsstore.ymlstage the per-arch exe.Verification
cargo fmt --check, clippy (no new warnings), andcargo test --workspace(55 new CLI tests) pass. The workspace tests also pass withoutsrc-tauri/binaries/present.quadrantmc.exeand the PATH script. The PATH script was tested against a scratch registry value.makeappx packaccepts the staged MSIX.Not verified locally: