# For agents and scripts (/docs/agents) ## JSON mode [#json-mode] Pass `--json` to any command: - the result is one JSON document on **stdout** - progress is JSON lines on **stderr**: `{"event":"step","message":"extracting Setup.zip"}`, `{"event":"progress","done":123,"total":456}` - errors are a JSON line on stderr, with exit code 1: `{"event":"error","message":"...","causes":[...]}` ```bash omavn --json install ~/Downloads/game.zip | jq .id omavn --json list | jq -r '.[].id' omavn --json run dies-irae --print # the exact program, argv, env, cwd ``` Nothing prompts in JSON mode or without a terminal. `remove` needs `--yes`. ## Docs as text [#docs-as-text] This site serves [`/llms.txt`](/llms.txt) (index) and [`/llms-full.txt`](/llms-full.txt) (everything), and each page has a markdown version. ## Building on omavn [#building-on-omavn] The CLI is a thin layer over the `omavn-core` crate. Launchers, GUIs, and library managers can use it directly: ```rust use omavn_core::{Paths, install, launch, library, report::Silent}; let paths = Paths::from_env()?; let game = install::install(&paths, &install::Options { source: "Himanatsu_final.zip".into(), ..Default::default() }, &Silent)?; let spec = launch::game(&paths, &game, None, &[], &Silent)?; spec.command().spawn()?; ``` Implement `Reporter` to render progress your own way. Game manifests are plain TOML in `~/.local/share/omavn/games/*/game.toml`, so tools in any language can read the library. # Catalog (/docs/catalog) The catalog is a folder of small TOML files, one per title. omavn matches an entry when every file it lists exists in the game folder (case-insensitive), and prefers the entry with the most matching files. ```toml id = "dies-irae" title = "Dies irae" engine = "malie" default_target = "fabula" notes = "Deluxe package with both editions." winetricks = [] # verbs applied at install, Proton games only [match] files = ["malie.exe", "malie_fabula.exe", "malie.ini"] [[target]] id = "fabula" name = "Dies irae ~Acta est Fabula~ HD" exe = "malie_fabula.exe" [[target]] id = "amantes" name = "Dies irae ~Amantes amentes~ HD (all ages)" exe = "malie.exe" [env] # any environment variables the game needs ``` All fields except `id`, `title`, and `match` are optional. Without `[[target]]`, omavn keeps its own entry point detection. ## Adding one [#adding-one] - **Just for you:** drop the file in `~/.config/omavn/catalog/`, then reinstall the game. - **For everyone:** add it to [`crates/omavn-core/catalog/`](https://github.com/Tetraslam/omavn/tree/master/crates/omavn-core/catalog) and open a pull request. The file name must be `.toml`; `cargo test` checks that. # Commands (/docs/commands) Run `omavn` on its own to see your library and what to do next. ## install [#install] ```bash omavn install [--id ID] [--title TITLE] [--proton] [--offline] omavn install --pick ``` Unpacks, installs, and registers a game, then fetches its VNDB metadata and art. `` can be a file or a folder. Alias: `add`. - `--id` sets the library id (default: from the catalog or the folder name) - `--proton` runs a Ren'Py game through Proton instead of natively - `--offline` skips VNDB and art - `--pick` chooses the download from a menu (Omarchy) ## run [#run] ```bash omavn run [--target ID] [--window | --gamescope] [-v] [--detach] [--print] [-- args...] ``` Launches a game. Alias: `play`. Ids, prefixes, and title fragments all work. - `--target` picks another entry point, like a different edition or a config tool (`omavn info` lists them) - `--window` / `--gamescope` override the display mode once (see [display](/docs/how-it-works#5-display)) - `-v` shows Proton's output; otherwise it goes to the game's `last-run.log` - `--print` shows the exact command instead of running it - `--detach` returns right away ## library [#library] ```bash omavn library ``` Pick a game from your library and play it. On Omarchy this is a full-screen cover grid; elsewhere a numbered list. Alias: `pick`. ## list, info [#list-info] ```bash omavn list omavn info ``` `info` shows the engine, runner, file and prefix paths, entry points, and notes. ## set [#set] ```bash omavn set display window # auto | gamescope | window omavn set target amantes # default entry point omavn set title "Dies irae" omavn set locale ja # Japanese locale for untranslated games omavn set env.DXVK_HUD fps # any environment variable omavn set env.DXVK_HUD # remove it ``` ## meta [#meta] ```bash omavn meta # refresh from VNDB omavn meta --vndb v548 # wrong match? pin the right entry omavn meta --all ``` Refreshes metadata, art, the library card, and the app launcher entry. ## remove [#remove] ```bash omavn remove [--yes] omavn remove --pick ``` Deletes the game, its prefix, its saves (see `omavn saves` first), and its launcher entry. Asks first unless you pass `--yes`. Alias: `rm`. ## saves [#saves] ```bash omavn saves # save folders, newest first omavn saves --open # open the newest in your file manager omavn saves --import /mnt/windows/Users/me/AppData/Roaming/light ``` Finds save data by what changed after install: the Wine prefix's AppData and Documents, `save` folders in the game, and `~/.renpy` for native Ren'Py games. Back these up before `omavn remove`. Coming from Windows? `--import` copies a save folder from your old Windows install (mounted drive, backup, USB stick) into the same place inside the game's prefix: everything after `Users//` is kept, so `AppData/Roaming/light` lands where Dies irae looks for it. Games' readmes usually say where their saves live. ## exec [#exec] ```bash omavn exec -- winecfg omavn exec -- /path/to/patch.exe ``` Runs a program inside a game's Wine prefix. Handy for fan patches and config tools. ## winetricks [#winetricks] ```bash omavn winetricks quartz wmp9 ``` Installs Windows components into a game's prefix, for games whose movies or installers need them. Proton's built-in versions are usually better, so only reach for this when something doesn't work. Installed verbs are recorded in the game's manifest. ## inspect [#inspect] ```bash omavn inspect ``` Reports what omavn would do (game or installer, engine, entry points) without installing. ## omarchy [#omarchy] ```bash omavn omarchy setup | remove | status ``` See [Omarchy](/docs/omarchy). ## runtime [#runtime] ```bash omavn runtime list omavn runtime install proton omavn runtime install renpy 8.5.2 ``` You rarely need this; runtimes are fetched when a game needs them. Set `OMAVN_PROTON` to a name from `runtime list` (or a path) to pin a Proton build. ## self [#self] ```bash omavn self update omavn self check ``` Updates omavn in place from the latest GitHub release (checksum verified). ## completions [#completions] ```bash omavn completions bash > ~/.local/share/bash-completion/completions/omavn ``` Also `zsh`, `fish`, `elvish`, `powershell`. The install script sets up bash and fish for you. ## doctor [#doctor] Checks python3, display, Vulkan (including the 32-bit drivers most VNs need), gamescope, disk space, and runtimes. ## feedback [#feedback] ```bash omavn feedback [--kind bug|game|idea] [--game GAME] [message...] ``` Opens a prefilled GitHub issue. See [Feedback](/docs/feedback). # Compatibility (/docs/compatibility) Every entry here was installed from the download exactly as the store delivers it, then launched. | Game | Download shape | Engine | Runner | Status | | --- | --- | --- | --- | --- | | Dies irae (Amantes amentes / Acta est Fabula) | 3 zips, each wrapping one volume of an SFX split RAR | Malie | Proton + gamescope | plays, incl. video and subtitles | | Yumina the Ethereal | `Setup.zip` (NSIS) plus 3 `.dat` zips it unpacks | custom | Proton + gamescope | installs unattended, plays | | HimaNatsu: Of Churches, Sunflowers, and Long Summers | single zip | Ren'Py 8.5 | native | plays | Your game not here? Try it, then tell us how it went: ```bash omavn feedback --kind game --game "works perfectly" ``` Reports of games that *work* are just as useful as broken ones. # Contributing (/docs/contributing) The most useful contribution is a report: install a game, play a bit, and run ```bash omavn feedback --kind game --game "works perfectly" # or what went wrong ``` ## Add a catalog entry [#add-a-catalog-entry] When a game needs something heuristics can't guess (a proper title, which exe is which edition, a VNDB id, environment variables), add `crates/omavn-core/catalog/.toml`. The format is on the [Catalog](/docs/catalog) page. `cargo test` checks every entry parses and that the file name matches its id. ## Work on omavn [#work-on-omavn] ```bash git clone https://github.com/Tetraslam/omavn && cd omavn cargo test cargo run -- install ~/Downloads/some-vn.zip ``` Layout: | Path | What | | --- | --- | | `crates/omavn-core` | the library: unpacking, detection, installs, runtimes, launching, art, Omarchy | | `crates/omavn` | the CLI, a thin layer over the library | | `crates/omavn-core/catalog` | per-game knowledge | | `docs` | this site (Fumadocs) | | `scripts/headless.sh` | an invisible desktop for testing games | CI runs `cargo fmt --check`, `cargo clippy -- -D warnings`, `cargo test`, and the docs lint and build. Run the same locally before opening a pull request. ## Testing games without touching your desktop [#testing-games-without-touching-your-desktop] `scripts/headless.sh` starts an invisible sway session (GPU-backed, with Xwayland, audio routed to a null sink), so games can be launched, clicked, and screenshotted while you keep working: ```bash scripts/headless.sh start scripts/headless.sh run omavn run dies-irae scripts/headless.sh shot /tmp/shot.png eval "$(scripts/headless.sh env)" # point your shell at the session scripts/headless.sh stop ``` For mouse input, attach `wayvnc` to the session and drive it with `vncdo`; focus the game window with `swaymsg` first. ## Releases [#releases] Tagging `vX.Y.Z` on `master` builds x86_64 and aarch64 binaries and publishes a GitHub release, which `omavn self update` and the install script pick up. # Feedback (/docs/feedback) ```bash omavn feedback "install hangs on the progress bar" omavn feedback --kind game --game yumina "works, but the opening movie is black" omavn feedback --kind idea "steam deck controls" ``` omavn opens a GitHub issue in your browser with the title, labels, and your system details (distro, kernel, session, Proton version) already filled in. With `--game`, it adds the engine, runner, entry points, and the name of the download you installed from. Nothing is sent until you press submit, and you can edit everything first. `--no-open` prints the link instead, which is handy over SSH. You can also [open an issue directly](https://github.com/Tetraslam/omavn/issues/new). # How it works (/docs/how-it-works) ## 1. Unwrap [#1-unwrap] Downloads come wrapped in layers. Dies irae from JAST is three zips, each holding one volume of a split RAR whose first volume is a self-extracting `.exe`. omavn peels layers until it reaches something playable: - groups multi-volume sets (`.part1.exe`/`.part2.rar`, `.rar`/`.r00`, `.7z.001`) - opens ISO disc images (via `bsdtar`) - detects RAR self-extractors by content, not name - decodes Shift-JIS file names in zips, which most Japanese releases use - drops `__MACOSX` and other packer junk It stops as soon as it finds a real `.exe`, so data archives that belong to an installer (Yumina's `yumina1.dat` is secretly a zip) are left alone. Your download is never modified; staging uses symlinks and only extracted layers take disk space. ## 2. Classify [#2-classify] The unwrapped folder is either a **game** or an **installer**. - Installers are fingerprinted (NSIS, Inno Setup, MSI, InstallShield, WiX) and run unattended under Proton when the framework supports it. Chained DirectX redist wizards are skipped, since Proton already provides those DLLs. - Games get an engine fingerprint (Ren'Py, KiriKiri, Malie, Siglus, BGI, NScripter, Artemis, CatSystem2, QLIE, YU-RIS, Unity, RPG Maker, TyranoScript) and a ranked list of entry points, with uninstallers, redists, and helper binaries filtered out. ## 3. Catalog [#3-catalog] Some things heuristics can't know: that `malie_fabula.exe` is *Acta est Fabula* and `malie.exe` is the all-ages *Amantes amentes*. The [catalog](/docs/catalog) fills those gaps per title. ## 4. Pick a runner [#4-pick-a-runner] | Runner | Used for | How | | --- | --- | --- | | native Ren'Py | Ren'Py 7.4+ and 8.x | runs the official Linux Ren'Py runtime of the same version against the game's files | | Proton | everything else | GE-Proton through umu-launcher, one Wine prefix per game | Native Ren'Py runs faster, uses your real audio and GPU stack, and touches nothing in the game folder. ## 5. Display [#5-display] Most VNs render at a fixed resolution (800x600, 1280x720) and read mouse positions in those pixels. When a tiling window manager resizes the window, the picture stretches but the game's idea of where you clicked does not, so buttons stop lining up with the cursor. With `display = "auto"` (the default), Proton games run inside a fullscreen [gamescope](https://github.com/ValveSoftware/gamescope) at your monitor's resolution: the game keeps its native size, gamescope scales it up with the aspect ratio intact, and maps the mouse to match. Without gamescope installed, games run in a plain window. Change it per game: ```bash omavn set display window # or gamescope, or auto omavn run --window # just this once ``` ## 6. Art [#6-art] After installing, omavn looks the game up on [VNDB](https://vndb.org) and downloads its cover and a screenshot, using only images VNDB rates as safe. It composes them into a 16:9 card for launchers and an icon for the app menu. Pin the right entry with `omavn meta --vndb ` if the guess is wrong, or skip it all with `--offline`. ## 7. Library [#7-library] Each game gets `~/.local/share/omavn/games//game.toml`, a plain manifest you can read or edit: ```toml id = "dies-irae" title = "Dies irae" engine = "malie" runner = "proton" files = "files" default_target = "fabula" vndb = "v548" [[targets]] id = "fabula" name = "Dies irae ~Acta est Fabula~ HD" exe = "malie_fabula.exe" ``` Per-game environment variables live in an `[env]` table; `omavn set locale ja` writes the Japanese locale there for untranslated releases. # Quickstart (/docs) omavn takes whatever you downloaded (a zip, a stack of split rars, an installer, a plain folder) and turns it into a game you can launch. It figures out the engine, runs installers unattended, and picks the best way to run it: natively where possible, through Proton otherwise. ## Install omavn [#install-omavn] ```bash curl -fsSL https://omavn.dev/install.sh | sh ``` On Omarchy, also run `omavn omarchy setup`. See [Installing omavn](/docs/installing) for details. ## Add a game [#add-a-game] Point it at the download exactly as you got it. Don't unzip anything first. ```bash omavn install ~/Downloads/Himanatsu_final.zip omavn install ~/Downloads/"Dies irae" # a folder of MG1041_1.zip, _2.zip, _3.zip omavn install ~/Downloads/"Yumina the Ethereal" # Setup.zip plus yumina1-3.dat ``` ## Play it [#play-it] ```bash omavn run dies-irae ``` Ids, prefixes, and title fragments all work: `omavn run dies`, `omavn run hima`. Or browse everything with `omavn library`; each game also shows up in your app launcher. ## Something broke? [#something-broke] ```bash omavn feedback --kind game --game dies-irae "voices cut out in chapter 2" ``` That opens a GitHub issue with your system details already filled in. See [Feedback](/docs/feedback). # Installing omavn (/docs/installing) ```bash curl -fsSL https://omavn.dev/install.sh | sh ``` Installs the latest release to `~/.local/bin/omavn` (x86_64 and aarch64 Linux). Update any time with: ```bash omavn self update ``` On Omarchy, follow up with `omavn omarchy setup` ([details](/docs/omarchy)). ## From source [#from-source] Needs a Rust toolchain ([rustup.rs](https://rustup.rs)) and a C++ compiler (for the bundled unrar). ```bash cargo install --git https://github.com/Tetraslam/omavn omavn ``` ## What omavn downloads for you [#what-omavn-downloads-for-you] Nothing is installed system-wide. Everything lives in `~/.local/share/omavn`, and omavn reuses what you already have before downloading anything. | Runtime | When | Reused from | | --- | --- | --- | | GE-Proton | first Windows game | Steam's `compatibilitytools.d`, Steam's own Proton | | umu-launcher | first Windows game | `umu-run` on your `PATH` | | gamescope | never downloaded; install it with your package manager | `gamescope` on your `PATH` | | Ren'Py (Linux) | first Ren'Py game of that version | | You need `python3` (umu-launcher is a Python app), a working GPU driver including its 32-bit Vulkan libraries (most VNs are 32-bit), and ideally gamescope. `omavn doctor` checks them. ```bash omavn doctor ``` ## Where things go [#where-things-go] | Path | What | | --- | --- | | `~/.local/share/omavn/games//files` | the game | | `~/.local/share/omavn/games//prefix` | its Wine prefix, including saves | | `~/.local/share/omavn/runtimes` | Proton, umu, Ren'Py | | `~/.local/share/omavn/library` | one card image per game, for launchers | | `~/.local/share/applications/omavn-.desktop` | app launcher entries | | `~/.config/omavn/catalog` | your own [catalog entries](/docs/catalog) | Set `OMAVN_HOME` to keep everything under one directory instead. # Omarchy (/docs/omarchy) ```bash omavn omarchy setup ``` That's it. Open the Omarchy menu and you'll find **Visual Novels**. ## What you get [#what-you-get] - **Super + Shift + V** opens your library (skipped if you've bound that combo to something else). - **Visual Novels in the menu.** Your library opens in the same full-screen cover grid as Omarchy's theme and wallpaper pickers. Type to filter, Enter to play. - **Install from the menu.** *Install → Gaming → Visual Novel* lets you pick a download from `~/Downloads`. A file inside a folder (like `Dies irae/MG1041_1.zip`) installs the whole folder, since multi-part downloads come that way. - **A notification when it's ready**, with the cover. Click it to play. - **Every game in the app launcher**, with an icon from its cover. - **Games look right.** Windows games run in gamescope, filling the screen with the right aspect and with clicks landing where you see the cursor. Hyprland rules keep them fully opaque (Omarchy's default window transparency is off for them) and stop the screen from idling while you read. - **Remove from the menu** too: *Remove → Visual Novel*. ## What it changes [#what-it-changes] Everything is marked and undoable: | Change | Where | | --- | --- | | installs `gamescope`, `umu-launcher`, and 32-bit GPU drivers | via `omarchy-pkg-add` and `omarchy-install-gaming-gpu-lib32` (asks for sudo) | | window rules and the keybinding | `~/.config/hypr/omavn.lua`, loaded by one `require("hypr.omavn")` line at the end of `~/.config/hypr/hyprland.lua` | | menu entries | three routes in `~/.config/omarchy/extensions/omarchy-menu.jsonc`; your existing entries and comments stay as they are | ```bash omavn omarchy status # what's set up omavn omarchy remove # undo the rules and menu entries (packages stay) omavn omarchy setup --skip-packages # no sudo ``` ## Window rules [#window-rules] Under gamescope every game window has the class `gamescope`. Games you switch to a plain window (`omavn set display window`) get the class `steam_app_omavn_`, so you can target one game in your own rules: ```lua o.window({ class = "^steam_app_omavn_dies_irae$" }, { fullscreen = true }) ``` Your own rules in `hyprland.lua` come before the omavn line, so for the same property omavn's wins. To override omavn, put your rule after `require("hypr.omavn")`. # Troubleshooting (/docs/troubleshooting) ## Clicks land in the wrong place, or the game looks stretched [#clicks-land-in-the-wrong-place-or-the-game-looks-stretched] The game's window was resized (tiling window managers do this) while the game kept its own resolution. Install gamescope and omavn uses it automatically: ```bash sudo pacman -S gamescope # or your distro's package; on Omarchy: omavn omarchy setup ``` If gamescope misbehaves on your GPU, fall back to a floating window with `omavn set display window` and make sure your window manager doesn't tile it. ## The game shows a settings dialog first [#the-game-shows-a-settings-dialog-first] Many VNs open a launcher or config dialog before the game, on Windows too. Pick your options and start the game; most have a "don't show again" box. ## An installer opened a window [#an-installer-opened-a-window] omavn runs NSIS, Inno Setup, and MSI installers unattended. Other frameworks (InstallShield, custom installers) need you to click through. Any install location works; omavn finds the game afterwards. ## Japanese text is garbled [#japanese-text-is-garbled] Untranslated Japanese releases often expect a Japanese system locale (their text is Shift-JIS): ```bash omavn set locale ja ``` The locale is generated inside Proton's container, so you don't need it installed on your system. Undo with `omavn set locale`. ## Use a different Proton [#use-a-different-proton] ```bash omavn runtime list OMAVN_PROTON=GE-Proton11-9 omavn run ``` ## See what's actually running [#see-whats-actually-running] ```bash omavn run --print ``` prints the full command, environment, and working directory, so you can run it by hand and read the output. ## Still stuck [#still-stuck] ```bash omavn feedback --kind game --game "what happened" ```