Skip to content

Latest commit

 

History

History
186 lines (151 loc) · 7.29 KB

cli.md

File metadata and controls

186 lines (151 loc) · 7.29 KB

CLI reference

accshift ships as a command-line binary alongside the desktop app, for scripting, Stream Deck macros and AI automation. It reads and writes the same config as the GUI: running both at once is safe thanks to an exclusive lock on mutating operations.

Install

Windows The desktop installer ships the CLI next to the app and adds the install directory to your user PATH, so accshift works in any new terminal right after install. A standalone accshift-cli_<version>_x64.exe binary is also available on Releases.

Linux The deb and rpm packages install the CLI to /usr/bin alongside the app. A standalone accshift-cli_<version>_linux_x86_64 binary is also on Releases.

macOS The .app bundles the CLI inside Contents/MacOS. Symlink it onto your PATH, for example into /usr/local/bin. A standalone accshift-cli_<version>_macos_aarch64 binary is also on Releases.

Building from source (cargo build --release -p accshift-cli) produces the binary at <target-directory>/release/accshift, or accshift.exe on Windows. The target directory defaults to target/; Cargo configuration or CARGO_TARGET_DIR can override it.

Commands

accshift platforms               # list platforms known to this build
accshift list <platform>         # list accounts for a platform
accshift list <platform> --folder <name>
accshift switch <platform> <account-id>
    [--online | --invisible]
    [--graceful | --force]
    [--admin | --no-admin]
    [--launch-options "..."]
accshift dry-run <platform> <account-id>
accshift descriptors             # what the user descriptor folder holds
accshift diag check              # check local health invariants
accshift diag logs --since 30m    # inspect recent log records
accshift diag bundle             # write a local diagnostic report

Every one of these needs the "Allow the accshift CLI" toggle in the app (Settings > General > Integrations). With it off they all exit 7 and do nothing, diag included.

--folder matches a name within the selected platform, without case sensitivity, and includes accounts in nested folders. Duplicate names are ambiguous and cause an error. Folder IDs and paths are not accepted.

The full diag command reference is in logging.md.

--graceful asks the launcher to close itself and waits for it, which is what you want by default because a launcher killed mid-write can corrupt its own config. --force terminates it instead, for the cases where it will not go.

dry-run prints the switch instead of performing it: every file, folder and registry value it would read, copy back or delete, every process it would close, and the launcher it would start. It walks the same descriptor the real switch walks, so the two cannot disagree. It opens nothing for writing and takes no lock, so it is safe to run at any time, including while the GUI is busy.

Platforms still implemented in code (Steam, Battle.net, Riot, Roblox) have no plan to show and answer dry_run_unsupported.

descriptors reads the folder where a user drops platforms of their own and reports both halves: the descriptors that loaded, and every file that was refused with the field that caused it. A platform missing from platforms is explained here rather than silently absent. It exits zero either way, rejected files included: the command was asked what the folder holds and it answered, so a script reads rejected instead of guessing from a status that would also mean "could not look". The format itself is in platform-descriptors.md.

Example:

$ accshift list steam
  ACCOUNT      NAME                 STEAM ID
* alice        Alice                76561198000000001
  bob          Bob the Builder      76561198000000002
  carol        carol_gg             76561198000000003

3 accounts.  * = currently signed in
$ accshift dry-run gog 51000000000000000
Dry run: switch gog to 51000000000000000. Nothing below is written.

Roots (a step outside these is refused):
  C:\Users\you\AppData\Local\GOG.com
  C:\ProgramData\GOG.com

  capture  C:\Users\you\AppData\Local\GOG.com\Galaxy\Configuration\config.json  <- ...\snapshots\51000000000000001\config.json
  capture  HKCU\Software\GOG.com\Galaxy\refreshToken  <- ...\snapshots\51000000000000001\registry_refresh_token.txt
  close    GalaxyClient.exe
  restore  C:\Users\you\AppData\Local\GOG.com\Galaxy\Configuration\config.json  <- ...\snapshots\51000000000000000\config.json
  launch   C:\Program Files (x86)\GOG Galaxy\GalaxyClient.exe

Output format

The default output is a readable table for humans on a TTY, and switches to JSON automatically when stdout is piped, so scripts and AI tools get a stable contract without passing an extra flag.

  • --json forces the JSON envelope everywhere, TTY included.
  • Errors always go to stderr, so stdout stays parseable even on failure.

The schema field is versioned. Consumers should check it rather than assume: a future incompatible shape ships as accshift.v2, and accshift.v1 keeps meaning what it means here.

Success envelope

{
  "schema": "accshift.v1",
  "ok": true,
  "command": "list",
  "data": {
    "platform": "steam",
    "folder": null,
    "accounts": [],
    "current": null
  }
}

Error envelope

{
  "schema": "accshift.v1",
  "ok": false,
  "command": "switch",
  "error": {
    "code": "lock_contended",
    "message": "Another accshift instance is running. Retry once it finishes, or close the GUI."
  }
}

Exit codes

Code Meaning
0 Success
1 Generic error
2 Unknown platform on this OS
3 Unknown account
4 Another accshift instance holds the lock
5 I/O error (paths, permissions)
6 PIN missing, unavailable, or incorrect
7 CLI disabled in Settings

Code 4 is retryable: the GUI and the CLI share one config, so a mutating operation takes an exclusive lock and a second one waits rather than corrupting it. Retry once the other instance finishes.

Codes 6 and 7 are deliberate refusals, not failures. Every subcommand respects the "Allow the accshift CLI" setting. Switching also checks the PIN lock configured in the app. An automated pipeline that starts returning 7 has been disabled through that setting. What the PIN lock does and does not protect is covered in the security policy.

Code 7 covers every subcommand, platforms, descriptors and all of diag included, and the check runs before the command is handed its arguments, so a refused run reads nothing and writes nothing. There is no exemption list: the CLI_GATE_EXEMPT const in crates/accshift-cli/src/main.rs is empty on purpose. Until 1.0.4 the toggle only covered list, switch and dry-run, so diag bundle still wrote a report carrying the redacted config summary on a machine whose owner had switched the CLI off. Diagnostics stay reachable without the CLI: the app has its own diagnostics screen.

A settings file that exists but cannot be read, with no usable .bak beside it, leaves the toggle unknown. Every subcommand then exits with 5 rather than assuming the CLI is allowed.