{"id":51363471,"url":"https://github.com/apocdev/pyops","last_synced_at":"2026-07-03T01:01:05.631Z","repository":{"id":367583757,"uuid":"1281426363","full_name":"ApocDev/pyops","owner":"ApocDev","description":"A web-based factory planner and in-game ops assistant for Factorio (Pyanodons) — YAFC-like, browser-based, with deep in-game integration and AI-assisted planning.","archived":false,"fork":false,"pushed_at":"2026-06-26T16:32:45.000Z","size":547,"stargazers_count":0,"open_issues_count":17,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-26T17:05:46.220Z","etag":null,"topics":["factorio","factory-planner","production-planner","pyanodons","react","tanstack-start","typescript","yafc"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ApocDev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-06-26T14:43:41.000Z","updated_at":"2026-06-26T16:32:47.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/ApocDev/pyops","commit_stats":null,"previous_names":["apocdev/pyops"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/ApocDev/pyops","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApocDev%2Fpyops","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApocDev%2Fpyops/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApocDev%2Fpyops/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApocDev%2Fpyops/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ApocDev","download_url":"https://codeload.github.com/ApocDev/pyops/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ApocDev%2Fpyops/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35068135,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["factorio","factory-planner","production-planner","pyanodons","react","tanstack-start","typescript","yafc"],"created_at":"2026-07-03T01:00:30.497Z","updated_at":"2026-07-03T01:01:05.595Z","avatar_url":"https://github.com/ApocDev.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PyOps\n\n\u003cimg src=\"app/public/logo.svg\" alt=\"PyOps logo\" width=\"100\"\u003e\n\nA web-based factory planner and in-game ops assistant for **Factorio**, built for\nthe **Pyanodons (Py)** overhaul — like [YAFC](https://github.com/Yafc-CE/yafc-ce),\nbut in the browser, simpler, with deep in-game integration and an AI-assisted\nplanner that actually understands Py's tangled recipe graph.\n\n**Just want to run it?** PyOps ships as a **cross-platform desktop app** — Linux,\nmacOS, and Windows — that bundles its own runtime and self-updates, so it needs no\ntoolchain. [**Download the latest release ↓**](#desktop-app) — or [run it from\nsource](#setup) to hack on it.\n\n---\n\n## What it does\n\n- **Design production blocks.** Pick one or more output goals (each with its own\n  target rate), choose the recipes and machines, set modules/beacons, and PyOps\n  solves the run-rates and building counts for the whole chain — including Py's cyclic recipe loops, fluid\n  temperatures, and fractional machine counts. A goal with no recipe behind it (an\n  unfinished block, or a producer lost to a data update) is flagged on the goal and\n  tinted on the block's tab and sidebar entry instead of breaking the whole solve.\n- **Balance the whole factory.** Every block's boundary flows (imports/exports)\n  roll up into a factory-wide ledger so you can see deficits, surpluses, and how a\n  change in one block ripples through the rest (\"what-if\").\n- **See what it costs to build.** Beyond the per-second flows, each block tracks its\n  one-time **build cost** — the materials needed to construct its buildings, in the\n  block's **Building summary** drawer — so something like steel shows up even when no\n  recipe in the chain consumes it.\n- **Size your logistics.** A toggle (the **Logistics** header control) shows, per\n  row, how many **belts** carry each item and how many **inserters or loaders**\n  feed one building at the planned rate — sized against your current research\n  (belt/inserter stacking follows the Horizon), with the belt/inserter tier and a\n  stacking override picked globally. A quick feasibility check for whether a build\n  is even possible with inserters or wants loaders. An optional toggle adds rocket\n  **launches/min** per good (`floor(rocket_lift_weight / item weight)` per rocket).\n- **Browse the data.** A searchable catalogue of every item, fluid, and recipe in\n  your exact mod set — used-in / produced-by, ingredients, products, machines.\n- **Track TURD choices.** Py's \"There's Usually a Recipe Difference\" tech upgrades\n  are first-class: each master shows every branch — its description, the recipes it\n  swaps or newly unlocks, and a hover diff of what actually changes (inputs,\n  outputs, and base throughput per second). Pick a path and every block re-solves\n  against it.\n- **Plan with AI.** An assistant (via OpenRouter) drafts whole production chains\n  and multi-block plans using tools over the recipe data, honouring what you can\n  build _now_ vs. _after research_.\n- **Keep tasks \u0026 notes.** A per-project planner: nested tasks (a markdown\n  description, a checklist of steps, and child tasks for bigger breakdowns) that\n  link to the recipes, items, fluids, research, and blocks they involve — plus a\n  separate scratch-notes surface for quick calcs and reminders. Kept in the\n  project's store, distinct from this repo's dev tracker.\n- **Reach into the running game.** A companion Factorio mod links over localhost\n  UDP: it shows a Helmod-style production-block panel in-game (with a toggle for\n  per-good belts \u0026 inserters), locates\n  producers/consumers via Factory Search, syncs your researched tech / TURD picks /\n  placed machines back into the planner, lets you **quick-capture a task** while\n  playing (with your location and selected entity as anchors), and can plan a\n  Cybersyn request combinator for a station in-game. The assistant can also read\n  the live factory through the bridge to ground its planning.\n- **Use it on any screen.** The UI is responsive: the full desktop layout on a\n  monitor, and on tablets, phones, and the Steam Deck the global nav and the\n  block/browse/assistant/tasks sidebars collapse into drawers, dense tables reflow\n  into readable cards, and reordering works by touch.\n\nPyOps runs locally on your own machine, alongside your Factorio install — it reads\nthe recipe data straight from the game and (optionally) talks to a running session.\n\n---\n\n## Desktop app\n\nThe easiest way to run PyOps is the self-contained **desktop app** — a\n[Tauri](https://tauri.app) window around the same server, bundling its own Node\nruntime so it needs no toolchain. It runs on **Linux, macOS, and Windows**, and\n**checks for updates on launch** (self-updating in place). Grab the build for your OS\nfrom the [Releases](https://github.com/ApocDev/pyops/releases) page:\n\n- **Linux** — `.AppImage` (`chmod +x` it and run; self-updates) or `.deb`\n- **macOS** — `.dmg`\n- **Windows** — the `-setup.exe` installer\n\nIt still needs **Factorio** installed locally to read your recipe data via a data\nsync — PyOps is built for the **Py** mods (and Py-specific views like TURD only\nappear when that data is present), but it'll load whatever mod set you sync. A fresh\ninstall starts empty — open **⚙ Settings › Game data** and run a sync on first\nlaunch, same as [from source](#setup) below. For how it's built and released, see\n[`docs/desktop.md`](docs/desktop.md).\n\n---\n\n## Screenshots\n\nThe **Factory** view rolls every block's imports/exports into one ledger — deficits,\nsurpluses, stock buffers, and a machine count compared against what you've actually\nplaced in-game. Every section sorts by any column (click a header; the choice sticks)\nand collapses out of the way. Deficits rank by **% of demand met** rather than raw\nrate, so a fully-starved intermediate outranks a half-fed bulk fluid no matter how\nsmall its numbers are.\n\n![Factory ledger — whole-factory balance with deficits, surpluses, and built-vs-required machines](docs/images/factory.png)\n\nThe **block editor** — pick one or more goals (each with its own target rate),\nchoose recipes / machines / modules, and the solver runs the rates and building\ncounts for the whole chain (cyclic recipes, fluid\ntemperatures, byproducts, fractional machines). New recipes default to the\nlowest-tier building and cheapest fuel; star a building or fuel in its picker to make\nit the **favorite** for that category, and new recipes there adopt it once it's\nresearched — existing blocks keep their picks. **Toggle a recipe off** to keep it in\nthe block but drop it from the solve — flip between two recipes for the same output to\ncompare them, or park future rows (T1 now, T2–T4 later) until you enable them. **Toggle\na whole block off** the same way: it stays in the sidebar (dimmed) and still opens for\nediting, but contributes nothing to the factory-wide totals until re-enabled. A block's\nicon follows its first goal by default — click the icon next to the block's name to\npick any item or fluid instead (with a one-click reset back to auto). Long chains fold\ninto **sub-blocks**: right-click a recipe's name to start a named group, add rows to it,\nand collapse it to a single line showing the chain's net flows (inputs → outputs,\nintermediates cancelled), machines and power. Purely visual — the solve is unchanged.\n\nDeliberate-spoilage steps (the uranium chain's decay, nagesium and friends) show their\n**storage buffer** right on the row: how many items sit mid-spoil at the solved\nthroughput (`rate × spoil time`) and roughly how many stacks that is — the \"how many\nchests do I need while it decays\" figure. For *incidental* spoilage — stuff rotting\nbecause it isn't consumed fast enough — a spoilable **surplus** gets a \"rots in X\"\nflag, and any spoilable can carry a **planned spoil loss** (right-click → Plan spoil\nloss): an expected rot rate the solver covers with extra production, shown in an\namber strip on the block balance.\n\nEach block also reports its **power and pollution budget** — electric draw and\npollution/min (machine base emissions × energy-consumption × pollution-module\neffects) — with factory-wide totals in the Factory header.\n\n\n\nNumbers everywhere scale their precision to the value: a `0.001/s` trickle block shows\nits real rates instead of a wall of rounded-down `0.00`, and only a true zero reads as\n`0`. Large figures render compact (`200K`) by default — switch to full (`200,000`) with\nthe **Compact large numbers** toggle under **⚙ Settings › Planning › Display**. Goal\nrates aren't chained to per-second either: click a goal's unit to cycle `/s → /min →\n/h` and enter science as `10/min` or a slow bootstrap as `0.5/h` — the unit sticks per\ngoal, while the solver keeps working in per-second underneath.\n\nNot everything is a throughput target. Right-click a goal and choose **Keep in stock**\nto turn it into a buffer goal — \"keep 100 on hand\" — with a refill window (default\n10 min, click to cycle): the machines are sized to rebuild the buffer within the\nwindow instead of chasing a made-up trickle rate. Stock production still counts in the\nfactory ledger, marked with a small **↻ stock** badge so refill demands read apart\nfrom continuous throughput.\n\n![Block editor — the Basic substrate bio-chain, solved with byproducts](docs/images/block-editor.png)\n\nThe **AI assistant** drafts a whole block from a goal: it resolves the chain, cuts\nshared high-fan-out inputs into their own sub-blocks, and flags byproducts, spoilage,\nand TURD upgrades.\n\n![AI assistant drafting a py science 1 production block](docs/images/assistant.png)\n\n**Browse** — a searchable catalogue of every item, fluid, and recipe in your exact mod\nset, with produced-by / used-in (here: Iron plate — 14 producers, 160 consumers).\n\n![Browse — Iron plate with its producers and consumers](docs/images/browse.png)\n\n---\n\n## Requirements\n\n_To run from source (below). The desktop app needs none of this._\n\n- **Node.js** (current LTS) and **pnpm** — the app's toolchain ([Vite+](https://viteplus.dev/),\n  the `vp` CLI) handles the rest.\n- **Factorio 2.0** installed locally, with the **Pyanodons** mod suite and\n  **pypostprocessing** — PyOps reads your recipe data by running the game's data\n  dump.\n- _Optional, for the in-game features:_ the PyOps companion mod (in [`mod/`](mod/))\n  and the [Factory Search](https://mods.factorio.com/mod/FactorySearch) mod.\n- _Optional, for the AI assistant:_ an [OpenRouter](https://openrouter.ai) API key.\n- _Optional, for external MCP clients:_ Codex and Claude Code can use the project\n  MCP configs in this repo once the app is running on `http://localhost:3000`.\n\n---\n\n## Setup\n\n```bash\ncd app\nvp install        # install dependencies\nvp dev            # start PyOps at http://localhost:3000\n```\n\nThe dev server also exposes the PyOps MCP tool surface at\n`http://localhost:3000/mcp`. The repo includes project-scoped config for Codex\n(`.codex/config.toml`) and Claude Code (`.mcp.json`) pointing at that endpoint;\nClaude Code asks for one-time approval of project MCP servers on first use.\n\nThen open PyOps, go to **⚙ Settings › Game data**, and run a sync. PyOps launches\nyour Factorio install headlessly, reads its recipe data, and loads it into a local\ndatabase. The first sync takes ~1–2 minutes (longer if you include icons). The same\ntab records and lists the mods (with versions) your data was dumped from, so you can\nsee exactly what your saved plans were built against.\n\nIf your Factorio isn't installed at the default Steam location, point PyOps at it\nwith the `FACTORIO_BIN` / `FACTORIO_DATA_DIR` settings below.\n\n### Reaching the dev server remotely (optional)\n\nTo open PyOps from your phone or another machine, expose the running dev server\nthrough a tunnel with [`scripts/tunnel-dev`](scripts/tunnel-dev):\n\n```bash\nscripts/tunnel-dev               # auto-pick cloudflared / ngrok / tailscale\nscripts/tunnel-dev tailscale     # force a provider\nscripts/tunnel-dev down          # tear tunnels back down\n```\n\nIt exposes `:3000` (override with `--port` / `$PYOPS_DEV_PORT`); run `vp dev`\nfirst. See `scripts/tunnel-dev --help` for custom hostnames (a cloudflared named\ntunnel via `--name`, an ngrok reserved domain via `--domain`; tailscale Funnel\nalways serves on the node's own MagicDNS name). The dev server already allows the\nproviders' domains; for your own custom domain add it to `PYOPS_ALLOWED_HOSTS`\n(comma-separated, or `true` to allow any host).\n\n### Using the in-game features\n\nThe companion mod ([`mod/`](mod/)) links the planner to a running game over\nlocalhost.\n\n**1. Put the mod in your Factorio mods folder.** The easiest way is the\n**Companion mod** card under **⚙ Settings › In-game link** — it detects your OS and\ninstalls the mod into your Factorio mods folder for you, either as a symlink\n(recommended — it tracks the repo, so pulling updates the mod) or a plain copy. On\nWindows the \"symlink\" is a directory junction, so it needs no admin or Developer\nMode.\n\nTo do it by hand instead, link or copy `mod/` into your mods folder as a folder\nnamed `pyops`, from the repo root:\n\n_Linux_\n\n```bash\nln -s \"$PWD/mod\" ~/.factorio/mods/pyops\n```\n\n_macOS_\n\n```bash\nln -s \"$PWD/mod\" ~/\"Library/Application Support/factorio/mods/pyops\"\n```\n\n_Windows (PowerShell, from the repo root)_\n\n```powershell\n# directory junction — no admin needed (what the in-app button uses):\nNew-Item -ItemType Junction -Path \"$env:APPDATA\\Factorio\\mods\\pyops\" -Target \"$PWD\\mod\"\n```\n\nOr just copy the `mod` folder into the mods folder and rename the copy to `pyops`\n(you'll need to re-copy after updates).\n\n**2. Launch Factorio.** Easiest: hit **Launch Factorio** in PyOps' **Live bridge**\ncard — it starts the game with `--enable-lua-udp` already set to a free port. For a\nSteam copy it launches through Steam (so cloud saves, overlay, and achievements keep\nworking), falling back to a direct launch only if Steam isn't reachable. To start\nthe game yourself, add `--enable-lua-udp 37658` (Steam: right-click PyOps' game →\nProperties → Launch Options). That port is the socket Factorio **binds for itself**,\nso it must be a _different_ free port than the app's bridge port (`37657`) — the two\ncan't share one loopback UDP port, or Factorio fails to open its socket with\n\"Address already in use\". Leave the mod's **PyOps bridge UDP port** at the app's\nport (`37657`).\n\nWith PyOps running, the in-game panel connects automatically — there's no bridge\ntoggle to flip. From there you get the production-block view, in-world locate, and\nlive sync of your research, TURD picks, and placed machines back into the planner.\n\n---\n\n## Configuration\n\nSet these in `app/.env.local` (or the environment). All are optional.\n\n| Setting              | Default                                            | Purpose                                                                                               |\n| -------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |\n| `FACTORIO_BIN`       | `~/.local/share/Steam/.../bin/x64/factorio`        | Path to the Factorio executable used for data syncs.                                                  |\n| `FACTORIO_DATA_DIR`  | `~/.factorio`                                      | Factorio user data (mods, `script-output`).                                                           |\n| `OPENROUTER_API_KEY` | —                                                  | AI **Assistant** key. Optional — set it here _or_ in **Settings → Assistant** (env wins).             |\n| `PYOPS_AGENT_MODEL`  | `~anthropic/claude-sonnet-latest`                  | Any OpenRouter model id. Optional — set it here, per chat, or in **Settings → Assistant** (env wins). |\n| `PYOPS_BRIDGE_PORT`  | `37657`                                            | UDP port the app's bridge listens on (mod's send target). Use a _different_ port for `--enable-lua-udp`. |\n| `DATABASE_URL`       | active project's file (else `projects/default.db`) | Override the local SQLite file.                                                                       |\n\n---\n\n## Documentation\n\nHow PyOps works under the hood lives in [`docs/`](docs/):\n\n- [Architecture](docs/architecture.md) — the one-app-plus-mod model and repo layout.\n- [Data pipeline](docs/data-pipeline.md) — how the Factorio data sync works.\n- [Block solver](docs/solver.md) — the planning math.\n- [Factorio bridge](docs/bridge.md) — the in-game link.\n- [AI assistant](docs/ai-assistant.md) — the planning agent.\n\n### Developing locally\n\nPyOps uses [Vite+](https://viteplus.dev/) (the `vp` CLI) as its toolchain. From\ninside [`app/`](app/):\n\n```bash\nvp install        # install dependencies (after pulling)\nvp dev            # dev server at http://localhost:3000\nvp check          # format + lint + typecheck — keep this clean\nvp test           # run the Vitest suite\n```\n\nThe end state of any change should be a clean `vp check`. The Factorio mod\n([`mod/`](mod/)) is pure Lua with no build step — edit in place and reload the game\nto test. For developer/agent visual checks, the MCP toolset includes\n`gameScreenshot` and, once the currently loaded mod has the dev command,\n`gameReloadMods` to invoke Factorio's mod reload over the bridge instead of using\ndesktop click automation. See [`AGENTS.md`](AGENTS.md) for the full toolchain commands and\nconventions (commit style, the database commands, and the project layout).\n\n---\n\n## Credits \u0026 inspiration\n\n- **[YAFC](https://github.com/Yafc-CE/yafc-ce)** — the planner model,\n  the cost-analysis approach, and the overall \"design blocks, balance the factory\"\n  shape.\n- **[Helmod](https://mods.factorio.com/mod/helmod)** — the in-game production-block\n  panel is heavily inspired by, if not close to ripped from, Helmod's\n  production-block view. No Helmod assets are bundled; colored cells use Factorio's\n  built-in `blue_slot`/`yellow_slot` styles.\n- **[Factory Search](https://mods.factorio.com/mod/FactorySearch)** — the\n  \"locate in game\" feature relays to Factory Search's remote interface rather than\n  reimplementing producer/consumer/storage search.\n- **[pypostprocessing](https://mods.factorio.com/mod/pypostprocessing)** — its\n  planner/YAFC integration is what makes a clean, planner-friendly data dump\n  possible.\n\n---\n\n## License\n\nPyOps is free software, licensed under the **GNU General Public License v3.0** —\nsee [`LICENSE`](LICENSE) for the full text.\n\nCopyright (C) 2026 ApocDev.\n\nIn short: you're free to use, study, modify, and share PyOps, including\ncommercially — but any distributed version (and any derivative built on it) must\nstay open under the same GPLv3 terms. It can't be taken closed-source. This\nmatches the lineage of the tools that inspired it ([YAFC](https://github.com/Yafc-CE/yafc-ce)\nand [Helmod](https://mods.factorio.com/mod/helmod) are GPLv3 as well).\n\nContributions are accepted under the same GPLv3 license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapocdev%2Fpyops","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapocdev%2Fpyops","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapocdev%2Fpyops/lists"}