A launcher and addon manager for World of Warcraft 3.3.5a clients, built with iced.
Download for Linux Download for Windows
Linux on ARM64 · Arch Linux (AUR)
Each is a single file built from the latest main;
nothing to install.
chmod +x old_launcher-linux-x86_64 (or
old_launcher-linux-arm64).old_launcher.exe. It isn't signed, so Windows may warn
about an unknown publisher: choose More info, then Run
anyway.old-launcher-git
from the AUR, which adds it to your applications menu.



Shortcuts: Ctrl+F search, F5 rescan, Esc close dialogs, Ctrl+Q quit.
index/wotlk.json is the launcher's own catalog,
generated by the indexer tool and committed here:
GITHUB_TOKEN=$(gh auth token) cargo run --release -p indexer # writes index/wotlk.json
The token only raises GitHub's API limits: a run makes about a hundred calls, more than GitHub allows anonymously.
The indexer lists every upstream source, downloads every archive, and
records the addon folders each one installs (with their
.toc title, version and interface), when it was last
updated, and the addon's own page at the source when it has one.
Listings that install the same folders are merged into one entry whose
downloads are ordered most recently updated first. Entries whose
download is dead or holds no addon are left out and reported, and links
to dead or hijacked sites are dropped.
The sources, in order of preference (the first one listing an addon describes it):
An addon's update date is the newest file date inside its archive, which for a repository snapshot is its last commit. locus313's zips are rebuilt daily, so for those it is the last commit touching the addon's folder.
The app embeds the copy of index/wotlk.json it was built
with, so the catalog shows instantly and offline. It then fetches the
published catalog, if there is one:
OLD_LAUNCHER_INDEX_URL=https://… cargo build --release
sets where the published catalog lives. Without it, the embedded copy is
all there is.OLD_LAUNCHER_INDEX=<url or path> at run time
points the app at any other catalog, such as a local
index/wotlk.json while working on the indexer.Sources live in indexer/src/source/, one module each, as
types implementing the Source trait (info
describes it for the catalog, list returns its listings).
Adding one means writing that module and adding it to the ordered list
in indexer/src/main.rs; a GitHub maintainer is one more
name in github::MAINTAINERS.
There is no database. Everything is read from the client folder itself:
Interface/AddOns and its .toc..old_launcher.toml marker (source, catalog entry, URL) into
each folder it creates. The client ignores it. Folders without a marker
show as installed manually, one card per folder..toc versions best match the
installed ones, or the preferred download when none does.WTF/Account/<account>/SavedVariables/<Addon>.lua
and the per-character
…/<realm>/<character>/SavedVariables/<Addon>.lua,
plus their .bak copies.Archives are extracted to a hidden staging folder inside
Interface/AddOns. The walk goes breadth-first until it
finds a folder holding a .toc. That folder moves into place
under the name its .toc declares, and the walk does not
descend into it, since deeper .toc files belong to embedded
libraries. So only Name/Name.toc layouts ever reach
Interface/AddOns, whatever the archive looks like.
Play starts Wow.exe from the client
folder on Windows. Elsewhere it runs the client's command with
sh, the way Steam runs launch options: the environment
variables are set and exported first, and %command% becomes
the quoted path to Wow.exe (wine %command%
when there is no command). ~ and $HOME expand
as in a terminal.
The only file outside the clients lists the client folders and how
each one starts: ~/.config/old_launcher/config.toml (the
platform config directory elsewhere), or
$OLD_LAUNCHER_CONFIG when set. If it can't be read, the
launcher does nothing else until you choose: it shows why, where the
file is, and which client folders overwriting it would forget, and
offers to edit it (then read it again), quit, or overwrite it with new
settings.
core/: data and filesystem logic, no GUI and no network
(TOC parsing, client detection, archive extraction,
install/uninstall/repair/clean, the catalog schema, adoption, launch
commands, and the library the list is filtered from).
Unit-tested against temporary directories.indexer/: the CLI that builds
index/wotlk.json from the upstream sources.src/: the iced app. lib.rs is the shell,
with one TEA cell per screen (setup, clients,
and addons with its cards and confirmation dialogs).
Screens are tested with iced_test::simulator.Nothing outside tests may panic on purpose: the workspace denies
unwrap, expect, panic!,
unreachable!, todo! and
unimplemented! through clippy (tests are exempt, see
clippy.toml). Whatever goes wrong while the app runs ends
up in the error banner at the top, which lists every problem until
dismissed.
cargo clippy --workspace --all-targets # also enforces the no-panic rule
cargo test --workspace
# Installs real catalog entries into a client, then uninstalls them
# (entries whose folders the client already has are skipped):
OLD_LAUNCHER_TEST_CLIENT="/path/to/World of Warcraft 3.3.5a" \
cargo test --lib addons -- --ignored