Factorio Mod Workshop
A maintainer's workbench for Factorio mods. Keeps track of everything you owe your mods — bugs to fix, features you meant to build, questions to answer — across every mod you own, from one place.
Built for maintainers with more mods than time, and for the AI agents helping them.
$ fmw inbox
== You owe a reply (1) ==
TR [bug ] 2026-08-31 0r Incompatibility with my favorite mod
6a93b26dead0beef42cd3c3b WH40k-Titans
fix shipped, reporter not told - released: 3d33eb
== Awaiting your testing (2) - run `fmw testplan` ==
c341fd WH40k-Titans: Error loading mods after update
== Threads awaiting triage (123, 28 hidden as resolved on the portal) ==
1. What it holds
Tickets are the centre: a bug to fix, a feature to build, an idea worth keeping. They stand on their own — many begin as a thought of yours or a message on Discord, and never touch the mod portal at all.
fmw track new Lightning "Configurable strike frequency" --kind feature
fmw track new WH40k-Titans "Pathfinding stalls on cliffs" --source discord:<url>
fmw track new 6a963b26... # or from a portal thread, title filled in
A ticket carries its analysis, the fix, and a test plan for when you next launch the game. One ticket can cover several mods, because large mods share code.
Discussions are one input among several — but the noisiest, and the only one with no tooling of its own.
2. Why the portal needs help
The mod portal has no API for discussions, no notion of a thread being handled, and no quick way to tell that four reports describe one bug. So a popular mod accumulates a hundred conversations you can neither search nor close, and every visit starts from scratch.
fmw gives that a memory.
- Nothing gets lost. Every discussion is mirrored locally with exact timestamps, so each sync reports precisely what is new. Repeat runs print nothing when nothing happened.
- Duplicates become one thing.
fmw searchfinds every thread describing a problem; one ticket cites them all — across mods, since large mods share code. - Most threads never need a ticket. A question you answered, a duplicate, a mistaken report: record the judgement and it leaves your inbox. Tickets stay for code changes.
- Shipping closes the loop. Mark a fix released and every thread that reported it comes back, once, asking you to tell the reporter.
- Agents stop where they must. An AI can triage, group and write fixes — it cannot launch Factorio. Fixes park in
needs-testingandfmw testplanbatches them into a single play session. - Your data is yours. Plain YAML and Markdown in a directory you choose, outside this repo, ready to be its own git repository.
3. Install
3.1. As a User
Install uv if you don't have it yet:
| OS | |
|---|---|
| MacOS & Linux | curl -LsSf https://astral.sh/uv/install.sh | sh |
| Windows | powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" |
Install fmw using uv:
uv tool install git+https://github.com/AivanF/factorio-mod-workshop
Create your workspace repository:
fmw init ~/factorio-workspace
Optional but recommended: specify the workspace location globally once, by setting FMW_WORKSPACE in your shell profile:
| Shell | |
|---|---|
| bash | echo 'export FMW_WORKSPACE=~/factorio-workspace' >> ~/.bashrc |
| zsh | echo 'export FMW_WORKSPACE=~/factorio-workspace' >> ~/.zshrc |
| fish | set -Ux FMW_WORKSPACE ~/factorio-workspace |
| PowerShell | setx FMW_WORKSPACE "$HOME\factorio-workspace" |
Or skip it and pass FMW_WORKSPACE env var or --workspace <path> arg to any command.
Finally, point it at your mods and pull everything in:
fmw repo add ~/code/my-factorio-mods # a monorepo, or one repo per mod
fmw discover # find them, read their portal metadata
fmw sync --all # fetch every discussion
3.2. Working on FMW itself
git clone https://github.com/AivanF/factorio-mod-workshop && cd factorio-mod-workshop
uv venv && uv pip install -e .
./.venv/bin/fmw init ~/factorio-workspace
./.venv/bin/fmw launcher --workspace ~/factorio-workspace
fmw launcher installs a small wrapper on your PATH that pins a workspace, so fmw works from any directory without setting anything — a POSIX sh script on Linux and macOS, a .cmd on Windows. Edits to the source take effect immediately.
Requires Python 3.10+. Developed on macOS and used on Linux; the Windows paths are implemented but untested — reports welcome.
4. Daily loop
fmw inbox # what needs a decision
fmw track new <mod> "..." # capture a bug, a feature, an idea
fmw sync # pull in what users posted
fmw thread <id> # read one discussion
fmw mark <id> ... # settle a conversation without a ticket
fmw testplan # batch pending fixes into one play session
fmw status # show workspace path & FMW statistics
Run it from inside a mod repository and it scopes itself to that mod, saying which one it picked.
5. Help
Every command carries its own prose — no need for this page or a checkout:
fmw help # overview and the daily loop
fmw sync --help # what a command is for, and its gotchas
fmw help --all # everything at once, for agents
Every command also takes --json.
6. Design
Three layers, deliberately separate:
cache/ |
what users actually said — disposable, refetched in minutes |
threads/<mod>.yaml |
what you decided about a conversation |
tracker/<mod>/*.md |
the work itself — tickets, whatever their origin |
A network sync writes only to the first, so it can never overwrite a judgement. fmw never writes to the mod portal: there is no write API, and replying is the maintainer's job.
7. Documentation
Using fmw — everything ships with the package, so it works from a uv tool install with no checkout:
fmw help workspace # file formats and every field value
fmw help workflow # the loop, and the mistakes it prevents
fmw help --all # the lot, in one call
Working on fmw:
- CHANGELOG.md — what changed in each release
- docs/portal-notes.md — how the mod portal behaves, including its traps
- CLAUDE.md — conventions for coding agents changing this repo
Metadata
Release files for factorio-mod-workshop 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| factorio_mod_workshop-0.1.1.tar.gz | 540.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| factorio_mod_workshop-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 605.8 kB
Release files / factorio_mod_workshop-0.1.1.tar.gz
| Download URL | factorio_mod_workshop-0.1.1.tar.gz |
|---|---|
| Size | 540.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c7b9d6e2e567e6755d448181eb547cd1670a334fffb93df8670949cd4ee6b50
|
|
BLAKE2b-256 checksum How to use checksums |
b738dcb8e31520773b4acc526de4b350bcc31e6225a7b351709a9bc8ec844d4e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.7
|
Release files / factorio_mod_workshop-0.1.1-py3-none-any.whl
| Download URL | factorio_mod_workshop-0.1.1-py3-none-any.whl |
|---|---|
| Size | 65.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
331c62216462a8b9406d5b54436f50a1176c26e051be2d09dc90a42f6f84f789
|
|
BLAKE2b-256 checksum How to use checksums |
a73712f4163fc039834626e9f65285e9ef4dd263df3e6968d7cccd83d034d356
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/4.0.2 CPython/3.10.7
|
Security for factorio-mod-workshop 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.