Azrael's Mods Guides

Modwright

Using it

Until everything below is in place, a Get set up box at the top of the Launch Pad tab lists the three steps (SteamCMD, Steam account, mods folder), each a link that does it, says how many are done and offers the next one as a button. It goes away once they are done. Once the mods folder and its mods are found, the Project card folds into one line (folder, game, branch); Change... or a click on that line opens it again, which leaves the mod list more room.

  1. Mods repo: press Browse... (or Ctrl+O) and pick the folder that holds your RimWorld mods (one sub-folder per mod, each with About/About.xml), or drop the folder onto the window. Folders you used before are in the drop-down, so switching repos is one click. The path cannot be typed in, so it cannot be mistyped.
  2. Steam account (on the Options tab, under Account): type your Steam login name. The status line says whether a saved login exists; the same status shows next to the Upload button, and clicking it opens Options. Install SteamCMD downloads it to %LocalAppData%\SteamCmdHelper\steamcmd (or uses <repo>\_tools\steamcmd if that exists).
  3. Log in happens automatically on the first upload. A SteamCMD window opens; type your password and the Steam Guard code there. This app never sees your password. Afterwards the login is cached. Logging in through SteamCMD can knock the regular Steam client offline; use Steam > Go Online afterwards.
  4. Tick the mods (Tick all picks every mod that is ready) and press Upload. Several mods upload one after another with a single login check; if Steam refuses the login part-way, the rest are not tried. When more than one mod was picked, or anything failed, a summary lists what happened to each mod (it is also in the log). Tick changed picks only the mods whose version Steam does not have yet (the window's upload --changed). Dry run does every check and builds the package but uploads nothing. The taskbar button shows the progress and flashes when a run ends while the window is in the background. If anything failed or was not reached, Retry failed uploads just those mods again.

Before anything is sent, the confirmation lists each mod and what it will do on Steam, with its change note. When Steam already has the version a ticked mod would upload, it says so at the top: raise the version first (F2) if the upload changes anything. Click a mod to read or edit its note; an edit changes only what is sent to Steam, not the changelog file (Use the changelog entry puts it back). In a git repo, Draft from git commits fills the note with one line per commit that touched the mod since its last upload from this PC: since its upload tag (Tag each upload in git) when there is one, else since that upload's time, else its newest ten commits. Fixup, squash, WIP and merge commits are left out. The same button is in the box that asks what changed in a new RimWorld version. If git packaging would leave a mod's uncommitted changes out, the confirmation offers to commit them first. While a mod uploads, the progress card shows the package size, how long it has been running and, once this PC has a few uploads in its history, about how long is left. When Steam turns an upload down, the summary says what to do (for example, log in again, wait out a login rate limit, or accept the Workshop agreement), and a refused login offers Log in again and retry.

Every package is checked for files that are rarely meant for players: .git or obj folders, source art such as .psd or .blend, debug and leftover files (.pdb, Thumbs.db, ...), archives, and very large files. These are warnings in the log; only an empty package is refused, because it would remove every file from the item. Paths that break for some players are warned about too: paths long enough to pass Windows' 260-character limit once installed, names that differ only in capital letters (they overwrite each other on Windows and macOS), and names Windows refuses (CON, NUL, aux.ogg, <>:"|?*, a trailing dot or space). A package that is missing About/About.xml is refused, because the mod would break for everyone who updates; that usually means a .gitattributes export-ignore rule dropped it. When packaging with git, files in the mod folder that git does not have (ignored by .gitignore or not committed) are compared against the package: a .dll left out that way stops the upload, since players would get the mod without its code, and anything else left out is a warning. Builds in Assemblies and in version folders such as 1.6/Assemblies are picked up even when *.dll is ignored. Right-click a mod and choose Package > Preview package... to see every file and its size before uploading. It says which folders hold most of the size (click Size to sort by it) and lists what players rarely need (source art, debug files, a Source folder); Leave these out of every package saves those patterns as LeaveOut in .steamhelper.json, for git packaging too.

Each upload remembers which files it sent (%LocalAppData%\SteamCmdHelper\manifests), so the next one of the same item says in the log what was added, changed and removed since then, and Preview package... marks each file. A package that is much smaller or larger than last time, or that lost many files, is warned about. When nothing at all changed since the last upload (and no Workshop page change goes with it), the app asks before uploading it again, since subscribers would only get the change note; the command line uploads it with a warning.

In a git repo, after a new item is created the app offers to commit its Workshop ID file, so nobody creates the item twice (Options > Git & GitHub can do it without asking). Tick Tag each upload in git there to tag the uploaded commit as <mod folder>-v<version>; tags stay local until you push them.

The list can be filtered by name, folder or Workshop ID (Ctrl+F), Hide up to date drops the mods Steam already has, and clicking a column header sorts by it (again to reverse, a third time for folder order). Right-click a mod to open its folder or changelog, copy its Workshop ID or link, see its upload history, preview its package, or open it on Steam. The strip under the list spells out everything the selected mod needs, in full.

When the window is wide enough, a details panel sits beside the list: the selected mod's preview image at a size you can see, the version to upload and the one on Steam, its subscribers, favourites, views, size and visibility on Steam, its last upload from this PC and its Workshop tags, what it still needs, the change note and description it will upload with, and buttons for editing its page, changing its version, opening it on Steam or in Explorer, previewing the package and its upload history. With nothing selected it counts the list by status. Drag the bar between list and panel to resize it, or turn it off in Options > Appearance to give the list the whole width; on a narrow window the panel stays out of the way so the columns keep their room.

Everything works from the keyboard. F1 (or ? > Keyboard shortcuts) lists the shortcuts: F5 refresh, Ctrl+O pick the mods folder, Ctrl+F filter, Space tick the selected mod, Enter edit its Workshop page, F2 change its version, Shift+F10 its right-click menu, Ctrl+Enter upload the ticked mods, Esc stop a running upload, Ctrl+Tab switch tabs, Ctrl+PageDown / Ctrl+PageUp move between the Options sections, and Alt with an underlined letter for any button or box. While you move around with Tab or the arrow keys, the focused control has a clear ring around it. Screen readers are told when an upload finishes and when a step is missing.

The log at the bottom stamps each line with the time and colours it by kind (blue notes, green success, orange warnings, red errors). The drop-down next to its title shows everything, only warnings and errors, or only errors; untick Auto-scroll to read back while an upload runs. Drag the bar between the mod list and the log (or Tab to it and use the arrow keys) to give either more room; the log keeps that height. Copy and Save... take the whole log whatever is shown, Clear empties it, and SteamCMD logs opens SteamCMD's own log folder, which is where to look when Steam turns an upload down. Every upload run's log is also saved on its own, from the window and the command line alike: Past logs lists them by time and what was uploaded, so a failure can be read back after the window was closed. The newest 50 are kept, in %LOCALAPPDATA%\SteamCmdHelper\logs.

The app uses a dark theme by default. The Theme drop-down under Options > Appearance offers Light, Kats (gunmetal grey with orange), Koneko (purple and black), Serina (purple and mint green), Wolfie (blue and green), Vickra (sapphire blue on emerald green), Kitomi (red and cyan on black with white text), Szendoo (dim grey with hot pink), Triphlx (electric blue on black), Tohma (crimson on royal blue), Skywolf (deep dark purple on black), Hunter (silver on black with touches of red), PlusBacon (teal on black), or Match Windows to follow Windows' light or dark app mode (it switches when Windows does). When Windows High Contrast is on, the app uses its contrast colours instead. Text size (100% to 175%) makes all text, and the layout with it, larger on top of Windows' own display scaling; it is used from the next start. The choices are saved for your Windows user.

The checks are kept basic. A row turns red and cannot be uploaded only for things that would make the upload fail or go wrong:

  • a new item without its preview image, or a preview over 1 MB (Steam refuses both)
  • an id file that is not a number, or a metadata file that cannot be read
  • the same rules as the Add Changenote mod. The version comes from <version> in About/Manifest.xml, or else <modVersion> in About/About.xml, and About/Changelog.txt must have an entry for that version: a line starting with the version number, plus the lines under it up to the next version line (lines starting with # are skipped). That entry becomes the Workshop change note.

Everything else is only a warning: missing build output, uncommitted tracked changes (git packaging uses HEAD), a changelog that already has an entry newer than the version to upload, and a Manifest.xml whose version differs from About.xml's (the manifest's is uploaded; F2 sets both). Hover over a row to see its problems and warnings; problems are also listed in the log.

The list columns:

  • Steam version: the version already on Steam. Steam does not store one, so it is read from the newest change note on the item's public changelog page (notes sent by this app, or by Add Changenote, start with the version). If that note has none, it shows what this PC last uploaded, unless Steam shows a later update (an upload from somewhere else), in which case it shows ?. Private items show ? until the first upload from this PC.
  • Updated: when the item was last updated, read live from Steam's public item details (one request for the whole list, no login). not public means Steam hides it from anonymous readers: private, friends only, or removed. Hover a row for the title, visibility and subscriber count on Steam.
  • To upload: the mod's current version. Double-click it (or press F2) to change it: type the new number, or press Patch, Minor or Major for the next one (1.2.3 becomes 1.2.4, 1.3.0 or 2.0.0). The new number is written to <version> in About/Manifest.xml (when it has one) and to <modVersion> in About/About.xml. The app then asks what changed and adds that as the new version's entry in About/Changelog.txt (newest first, or at the end if the file lists the oldest version first), so the upload is not refused for a missing entry. If you skip it, double-click the row's Status to write it later.
  • Workshop ID: from the mod's About/PublishedFileId.txt; 0 means the upload creates a new item.
  • Preview: a thumbnail of the preview image; a red frame means it is over Steam's 1 MB limit, ✖ that it is missing (hover for the size). Right-click a mod and choose Package > Shrink preview image under 1 MB to re-save an oversized preview just small enough (the original is kept in %LocalAppData%\SteamCmdHelper\preview-backups).
  • Status: a badge, followed by the first problem or warning when there is one: Fix (red, can't be uploaded), Failed (red, failed in the last run), Changed (amber, Steam has an older version), New (blue, not on Steam yet), Up to date (green, Steam already has this version) or Ready (the version on Steam is not known yet).

Workshop page: title, description and visibility

Select a mod and press Workshop page... (or right-click it, or double-click its name). The editor reads the item's current title, description and visibility from Steam. Tick what to change; the changes are kept and sent with that mod's next upload (the confirmation lists them), then cleared (an upload from the command line sends them too). Unticked fields stay as they are on Steam. For a mod not on Steam yet, ticked fields replace the name, description file and private visibility it would be created with. SteamCMD cannot change tags, so the editor only shows them; see Workshop tags below.

Workshop tags

Players filter the Workshop by tags, such as Mod and the game versions (1.6, 1.7). SteamCMD's build file has no way to send tags, so after each upload the app sets them through the Steam client instead, the same way RimWorld's own uploader does. A mod gets Mod plus one tag per <li> under supportedVersions in About/About.xml (1.6.4104 counts as 1.6). Version tags the mod no longer lists are taken off, and any other tag on the item is kept. To fix mods uploaded before this, right-click one and choose On Steam > Update Workshop tags: that sends only the tags, not the files.

The Steam client has to be running and signed in as the account that owns the mod (and the game), because Steam only takes tag changes from the game's side. While the tags are sent, Steam briefly shows you as playing the game. If it fails, the upload still counts and the log says why. Turn it off with Set Workshop tags after each upload under Options > Uploading.

Preview image in the same editor replaces the item's preview on Steam with its next upload: Use the mod's preview takes About/Preview.png (after you changed it), or Choose... any PNG, JPG or GIF up to 1 MB. Without it, the preview on Steam is left alone; it is otherwise only sent when an item is created.

When you upload a mod that is on Steam and has a description file (About/steam_description.txt), the app checks whether the file differs from the Workshop page and offers to send it with the upload. Public and unlisted items are compared with their page on Steam; other items with what this PC last sent. Options > Workshop page can send it every time without asking, or never. The command line sends it only when that is set to Always send it.

The same right-click menu has Package > Upload history... (every upload of the mod made from this PC: when, which version, and the change note sent) and Open on Steam (the item's page in your browser).

How change notes look on Steam

Steam's change notes use BBCode. Options > Workshop page has a template for the current mods folder, wrapped around every note sent to Steam: {note} is the changelog entry and {name}, {version}, {date} (yyyy-MM-dd) and {game} fill themselves in, for example

[b]{name} {version}[/b] ({date})
{note}

A template without {note} gets the entry after it. Start with {version}: the Steam version column reads the version from the start of the newest note. The template and the credit line change only what Steam gets; the changelog file, the upload history and Discord announcements keep the entry as written.

Profiles, announcements and dependencies

Options > Account > Profiles saves the current mods folder, Steam account and SteamCMD under a name; pick a profile to switch all three at once (handy for several projects or a second Steam account).

Options > Uploading > After uploading is set per mods folder. Paste a Discord channel's webhook link (channel settings > Integrations > Webhooks) and each successful update is posted there with its name, version, change note and Workshop link; Send test checks the link. Mentions are switched off, so an @everyone in a changelog pings nobody. Tick Make a GitHub release to also create a release with the same notes on the uploaded commit, using the gh tool (run gh auth login once; the commit must be pushed). New items are created private, so they are never announced. The webhook link is a secret, so it is kept in your settings, not in the repo.

Mods that name other Workshop items in their About.xml (modDependencies, or any steamcommunity.com/sharedfiles/filedetails/?id= link) are checked against Steam when the list loads. A dependency that is private, removed or banned shows as a warning, since subscribers could not get it.

The row tooltip shows each item's subscriber count and how it has changed this week and since the last upload from this PC. Counts are saved once a day in %LocalAppData%\SteamCmdHelper\stats.json, so the trend fills in over time.

Command line (scripts and CI)

The same exe uploads without opening the window. It uses the repo, account and SteamCMD picked in the window unless you pass them, runs the same checks and upload code, and prints a summary at the end.

SteamCmdHelper upload MyMod OtherMod          # by folder or display name
SteamCmdHelper upload --all --dry-run         # check and package every ready mod, upload nothing
SteamCmdHelper upload --changed               # only the mods whose version Steam does not have yet
SteamCmdHelper upload MyMod --ref release      # package the release branch instead of the checked-out commit
SteamCmdHelper upload MyMod --test             # send it to the mod's private test item
SteamCmdHelper upload --all --repo D:\mods --account mysteamname --log upload.log
SteamCmdHelper upload MyMod --note "Hotfix for the save bug"   # this change note instead of the changelog's
SteamCmdHelper upload --changed --note-from-git --tag --announce # notes from commits, then tag and announce
SteamCmdHelper upload --changed --json        # only a JSON summary on stdout; progress goes to stderr
SteamCmdHelper list                           # each mod's version, Workshop id and status
SteamCmdHelper list --json                    # the same as JSON, for scripts
SteamCmdHelper version MyMod patch --note "- Fixed the thing"   # 1.2.3 -> 1.2.4, with its changelog entry
SteamCmdHelper update                         # install the newest release of the helper (--check: only report it)
SteamCmdHelper upload --changed --one-session --verify   # one SteamCMD login, then check each upload on Steam
SteamCmdHelper download MyMod --to D:\restore  # Steam's copy of a mod, into an empty folder
SteamCmdHelper verify MyMod                   # compare Steam's copy with this PC's last upload
SteamCmdHelper game-builds                    # the game's public build and betas, and what changed
SteamCmdHelper test-install --to D:\rw-beta --branch unstable MyMod   # game beta install with MyMod and its dependencies
SteamCmdHelper ci-setup                       # write a GitHub Actions workflow that uploads on a v* tag
SteamCmdHelper login-secret                   # SteamCMD's saved login, for that workflow's secret
SteamCmdHelper upload --group Core --tag --push-tags --run-after   # a saved group; push the tags; run the after-upload command
SteamCmdHelper list --markdown                # every mod with its version and Workshop link (also --csv)
SteamCmdHelper history --csv                  # this PC's uploads as CSV
SteamCmdHelper note MyMod                     # the change note exactly as Steam would get it
SteamCmdHelper game-version 1.7 --all         # add a RimWorld version to every mod (version folder and loadFolders.xml too)
SteamCmdHelper doctor --login                 # check everything an upload needs and say what to fix
SteamCmdHelper lint --strict                  # check every mod (About.xml too) without uploading; exit 1 if any is blocked
SteamCmdHelper schedule --at "tomorrow 18:00" MyMod   # upload later through Windows Task Scheduler (--list, --cancel 1)
SteamCmdHelper help                           # every option
  • The Steam login must already be saved: log in once from the window (Options > Account > Log in...). The command checks it once, then uploads each mod in turn.
  • A named mod that needs fixing, or does not exist, stops the command before anything is uploaded. --all skips such mods and says why. --changed also skips mods whose version Steam already has, found the same way as the window's Steam version column (the newest change note on Steam, else this PC's uploads); a mod whose version on Steam is not known is uploaded. With nothing to upload it exits 0, so it can run after every push. New items need --allow-create.
  • After an upload, --tag tags each uploaded commit as <folder>-v<version> (git packaging only), --commit-ids commits the Workshop id files of newly created items, and --announce posts to the Discord webhook and makes the GitHub releases set up for the folder in the window (Options > Uploading > After uploading). These are the steps the window offers; a dry run does none of them.
  • --note "..." uploads every mod with that change note instead of its changelog entry. --note-from-git drafts each note from the mod's commits since its last upload, like Draft from git commits in the window; a mod with no such commits keeps its changelog entry.
  • upload --json prints one JSON object on standard output, whatever happened: ok, exitCode, error (why nothing ran), and each mod's status (uploaded, created, checked, failed or notrun), workshopId, message and tag. Everything else goes to standard error.
  • Exit codes: 0 everything worked, 1 a mod failed or was not run, 2 bad arguments or nothing to upload, 3 SteamCMD missing or not logged in.
  • SteamCMD runs with +@ShutdownOnFailedCommand 1 +@NoPromptForPassword 1 whenever nobody can type into it, so an expired login or a Steam Guard prompt ends the run with an error instead of leaving a scheduled task or CI job waiting until it is killed.
  • The app is a Windows program, so in a cmd window the prompt comes back before the output finishes. Use start /wait SteamCmdHelper upload ... (or Start-Process -Wait in PowerShell) when the next line needs the result, or --log <file>. Redirected output (CI steps, > out.txt) and exit codes work as usual.

Build step, uploading from a branch, test items and rolling back

Options > Uploading has settings for the current mods folder, kept in your settings and never in the repo:

  • Build step: a command run in the mods folder before anything is packaged (for example dotnet build -c Release, or a script), for uploads and dry runs alike. If it fails, nothing is uploaded and its output is in the log. The command line runs it too (--no-build skips it).
  • Upload from: a git branch or tag to package instead of the checked-out commit, so a release branch can go out while you work on another. The version and change note are read from that branch. --ref does the same on the command line.
  • Try again when Steam is busy: an update that fails because Steam timed out, was busy or could not be reached is tried once more after 30 seconds before it counts as failed (on by default; new items are never retried).

Upload to test items (next to Dry run) sends each ticked mod to its own private copy on Steam instead of the real item: the first time, a private item titled " (test)" is created and its id saved to workshop_id.test.txt in the mod folder (git-ignore it; it is never packaged). Subscribers of the real item get nothing, and pending Workshop page changes, the upload history, tags and announcements all wait for the real upload. Subscribe to the test item in the game to check the build first. --test does the same on the command line.

To roll back a bad update, right-click the mod > Package > Upload history..., pick an earlier upload and press Upload this version again. In a git repo with git packaging, the app packages the commit that upload came from (its upload tag when Tag each upload in git is on, else the newest commit at that time) and sends it with the old change note marked as rolled back. Your working folder is not touched; raise the version for the next real update.

More from SteamCMD

  • One SteamCMD login per batch (Options > Uploading, off by default; --one-session): every ticked mod is packaged and checked first, then SteamCMD logs in once and uploads them one after another. Without it, each mod gets its own SteamCMD run and login. SteamCMD's output is split per mod at each Success. or failure line, and each mod is still judged on its own (and asked of Steam, like a single upload). A refused login stops the batch as before.
  • Check each upload (Options > Uploading, off by default; --verify): after an upload, the item is downloaded again with workshop_download_item, the way subscribers get it, and its files are compared with what was sent. A difference is a warning in the log. Steam can hand out the previous version for a few minutes after an upload.
  • Check what Steam hands out (right-click a mod > On Steam; verify <mod>) does the same at any time, against this PC's last upload of the mod.
  • Download from Steam... (right-click a mod > On Steam; download <mod|id> --to <folder>) saves Steam's copy into an empty folder, for when the local copy is lost or broken. Unlike rolling back, it does not need git.
  • The account must own RimWorld. The first time an account uploads, the app reads its licenses with licenses_print and warns when the game is not among them, since Steam refuses Workshop uploads from accounts that don't own it. A game borrowed through Family Sharing does not count. The command line prints the same warning.
  • Game branches (Options > SteamCMD; game-builds) lists the game's public build and betas with app_info_print. At start-up (at most every 12 hours, and only once SteamCMD is installed) the app says in the log when the game got a new public build or a beta changed, which is when mods break and supported versions need a bump. Turn it off under Options > SteamCMD.
  • Try in a game beta... (right-click a mod > On Steam, or Options > SteamCMD; test-install) installs a separate copy of the game on any branch with app_update -beta, into an empty folder (by default under %LocalAppData%\SteamCmdHelper\test-installs). With a mod selected, it then puts that mod, packaged as an upload would, and every Workshop item it lists as a dependency into the game's Mods folder. Start the game's program in that folder to try the mod on the next game version; your normal Steam install is not touched. The first install downloads the whole game. A beta with a password takes it in the dialog (or --beta-password); it is on SteamCMD's command line while it runs.
  • Upload from GitHub Actions (Options > Git & GitHub; ci-setup) writes .github/workflows/steam-workshop-upload.yml into the mods folder. On a Windows runner it downloads SteamCMD and this program, restores SteamCMD's saved login from a secret, and runs upload --changed whenever a tag starting with v is pushed (or from the Actions tab, with a dry-run choice). Add two repository secrets: STEAM_ACCOUNT (your login name) and STEAM_CONFIG_VDF, which Copy login secret... (or login-secret) gives you. That text is SteamCMD's saved login: whoever has it can use the login until it expires, so paste it only into the secret, and keep write access to the repo tight. When CI uploads start failing with a login error, log in again in the app and update the secret.

Three more parts of the Workshop page go through the Steam client after an upload, like tags (the client has to be running as the mod's owner). Each can be turned off under Options > Uploading, and right-click > On Steam > Update required items, gallery and languages sends them without uploading.

  • Required items. The Workshop links in a mod's About.xml (modDependencies with a steamWorkshopUrl) become the page's "Required items", so subscribers are offered them. Items the app added are taken off when the mod stops listing them; items you added by hand on Steam stay.
  • Gallery. The mod's Gallery folder holds PNG, JPG and GIF images plus an optional videos.txt of YouTube links. The page's extra images and videos are made to match it. The folder is never packaged.
  • Descriptions in other languages. A file next to the description file such as steam_description.german.txt (or .de.txt, .zh.txt and other short codes) is that language's description; a first line Title: ... sets the title. Only changed images and translations are sent again.

Options > Workshop page > Description has a footer for the mods folder: it is added to the end of every description sent from a description file (with {name}, {id} and {game} filled in), never twice.

Workshop pages of ticked mods... (right-click > Ticked mods > Workshop pages, with several mods ticked) finds and replaces text in, or appends a line to, every ticked mod's description, and sets their visibility, all sent with their next upload.

Checks, stats and new mods

  • RimWorld checks. Before upload the list flags a missing or repeated packageId, XML in Defs, Patches, Languages or About that does not parse, loadFolders.xml entries pointing at missing folders, version folders that supportedVersions does not list, Keyed translations missing keys English has (or keeping ones it dropped), a bundled 0Harmony.dll, and Harmony used without brrainz.harmony in modDependencies.
  • Before you confirm the upload, it says when the git branch is behind its upstream or not pushed, points out unclosed BBCode tags in the note or description, and Preview as on Steam opens the note as Steam shows it.
  • Dependency updates. The upload confirmation says when a Workshop item a mod needs was updated since the mod's last upload, so you can test against it first.
  • Stats and comments... (right-click > On Steam) charts subscribers, favourites, views and lifetime subscribers per mod or for the whole folder from the daily counts, and shows how many comments are new. Comments are counted through the Steam client, on request or at start-up when Options > Workshop page says so.
  • New mod (Ctrl+N, or the empty list) makes a ready-to-upload mod folder: About.xml with a packageId, the supported versions, a placeholder preview, the first changelog entry, the description file, and optionally a C# project with Harmony that builds into the newest version's Assemblies folder.
  • What's new opens after the app updates itself, with the changes since the version you had (also under Options > About).
  • Moving to another PC. Options > About > Export settings... saves settings, profiles, per-folder options and upload history in one zip; Import settings... on the other PC backs up what is there first and asks where each mods folder is now. The file can contain Discord webhook links, so keep it private.

Release helpers

  • Version hint: the version dialog (F2) marks the bump your commits since the last upload suggest: major for BREAKING CHANGE or feat!:, minor for feat: or "Add ...", patch otherwise. The upload confirmation warns when the version looks too small for them.
  • Release checklist: your own steps per mods folder (Options > Uploading), ticked off in the upload confirmation. "Don't upload until every step is ticked" makes it a must; dry runs never need it.
  • Mod families: when picked mods need each other (modDependencies, else Workshop links), the ones others need go up first, and if one fails, the mods that need it are not uploaded.
  • Package > Make a preview image draws a title card over a screenshot or a colour; Workshop description from README turns README.md into Steam BBCode in the description file, with a preview.
  • The log notes subscriber milestones (100, 1,000, ...) and a noticeable drop in a week.

Groups, the command palette and uploading later

  • Groups (Mods card) saves the ticked mods as a named group for the mods folder and ticks a group again in one click. upload --group <name> uploads one from the command line.
  • Ctrl+K (or Ctrl+Shift+P) opens a search over every button, menu item and Options section, with its shortcut.
  • Later... next to Upload schedules the ticked mods for a time you pick. Windows Task Scheduler runs the command line (upload ... --repo ...) as you, with the saved Steam login, so the window need not stay open; the PC must be on and you signed in, and if it was off it runs as soon as it can. The same window lists and cancels them. Its output goes to the past logs.
  • Ticked mods, all at once (right-click > Ticked mods, with two or more ticked): change their version, or add a new game version to supportedVersions, copying the newest version folder and adding it to loadFolders.xml.
  • A Windows notification says how a run went when the window is in the background (Options > Uploading).

After uploading: tags, a command and kept packages

  • Push the tags made by Tag each upload in git to the remote straight away (Options > Git & GitHub).
  • Command after uploading (Options > Uploading, per mods folder) runs after each successful upload, in the mods folder, with these environment variables: SCH_MOD_NAME, SCH_MOD_FOLDER, SCH_MOD_DIR, SCH_VERSION, SCH_WORKSHOP_ID, SCH_WORKSHOP_URL, SCH_CREATED, SCH_APP_ID, SCH_COMMIT and SCH_NOTE_FILE (a file with the change note as sent). Like the build step it comes from this PC's settings, never from the repo.
  • Keep a zip of what each upload sent (Options > Uploading) saves exactly what was sent (the newest 5 per mod); Uploaded packages on the right-click menu's Package submenu opens the folder.
  • Copy > The mod list as Markdown, Steam BBCode or CSV, and Export CSV in the history window.

Check setup

Options > About > Check setup (or SteamCmdHelper doctor) checks the mods folder and its layout file, how many mods need fixing, SteamCMD and the saved login, git and gh when they are used, the Discord link, the Steam client when tags or required items go through it, free disk space and the data folder, and says what to fix. The window really logs in with the saved login; on the command line add --login for that. Nothing is changed.

The app in other languages

Options > Appearance > Language shows the windows in Deutsch, Русский or 简体中文 from the next start. Log lines and messages stay in English, and any text a translation leaves out is shown in English. To fix a translation or add a language, press Make a translation file..., fill in the empty texts (keep the & before a letter: it marks the Alt key), and put the file in the folder Open the languages folder opens. Open the windows you want covered first, so their text is in the file. Translations are welcome as pull requests to Languages/.

Which Steam login each feature uses

SteamCMD can log in two ways. Anonymous needs no account and can only read public information. Everything that touches your games or Workshop items needs the saved login: the account you type under Options > Account, logged in once in SteamCMD's own window. That account has to own RimWorld.

What Login Why
Upload, create items, test items, roll back Saved Steam only takes Workshop changes from the item's owner, who must own the game
Check each upload, Check what Steam hands out, Download from Steam Saved Steam refuses anonymous Workshop downloads for most games, RimWorld included
Try in a game beta (installing the game) Saved Installing a game needs an account that owns it
The ownership check Saved It reads that account's licenses
Game branches, the new-build notice Anonymous A game's branches and build ids are public
Steam version, Updated, subscribers, the game's name None (Steam's web pages) Read from public Workshop pages without SteamCMD
Workshop tags, required items, gallery, other languages, comment counts The Steam client SteamCMD can't set these, so the running Steam client does it as the signed-in account
Drop Pod: send the active mods to a Steam collection The Steam client SteamCMD can't make collections; the signed-in account must own the game (and the collection, to update it)
GitHub Actions upload Saved, copied into a secret The runner has no one to type a password, so it reuses the saved login

Because Steam lets an account sign in once at a time, SteamCMD's login takes the Steam client's place when both use the same account, and the client goes offline. With Options > Uploading > Bring the Steam client back online (on by default), a Steam that was running before the upload is restarted in the tray afterwards and signs back in with its saved login ("Remember me"). Using a second Steam account for SteamCMD avoids this altogether, but that account must own the game and be able to update the items.

When you need to log in: the first time you upload, download or install, the app opens SteamCMD's window for your password and Steam Guard code. Afterwards Steam keeps the login until it expires. When it does (or you change your password), the next job that needs it says so and offers to log in again. Anonymous jobs never ask.

Mods not on Steam yet

Tick Allow creating new items. They are created private, with the title, description and preview image from the mod's About folder. The new id is saved to About/PublishedFileId.txt; commit it.

From the README on GitHub.