🇪🇸 Léelo en español — this page, in Spanish.
Edit the interior (IVA) of your Kerbal Space Program cockpits in your browser — no Unity needed.
IVA Forge bakes a 3D catalog of the crew cabins already installed in your game, lets you drag, rotate and scale props onto the real cockpit hull with what-you-see-is-what-you-get feedback, and writes your changes back as a ModuleManager patch — with a backup and one-click undo. It never touches the original files of Squad or any mod.
Status: v1.0.2 released — download. Windows-only, KSP 1.12.x. Tested against a limited modlist — please report cabins that fail to bake (see Troubleshooting).
Today the only way to re-decorate an IVA is Unity 2019.4.18f1 + PartTools: a heavy, fragile
setup that the community itself calls "extremely tedious", or editing the .cfg by hand and
relaunching the game to see every change. IVA Forge replaces that loop with a browser editor
and a game-accurate 3D preview, so you iterate without opening Unity and without restarting
KSP for each tweak.
- 3D cabin viewer — walk any installed crew cabin from the pilot's eye. Real hull, real props, real prop textures and RPM/MAS labels baked from your install.
- WYSIWYG prop editor — drag-and-drop from a searchable prop library sorted into 16 shelves by
what a prop is (monitors, annunciators, knobs, flight controls, seats, hatches…); move/rotate/scale
gizmos with snap and a ratio toggle that keeps a prop's proportions while you resize it; props go
in facing you and magnetize to the visible interior skin, so they sit on the wall instead of
floating or sinking into it. Copy, cut and paste with
Ctrl+C/Ctrl+X/Ctrl+V— a whole selection pastes as one block, keeping its relative layout, even in a different cabin. - Nothing is committed until you say so — the editor's buttons are grouped into Design (save · load saved · restore original · clear all) and Apply & share. Restore original puts the cabin back exactly as its mod ships it, without touching your saved design or the game.
- IVA Switch aware — every interior in a part's IVA Switch menu is baked and listed with the same name the game shows, with the one your install currently loads marked. Open a variant your game is not loading and the viewer says so, before you spend an evening editing an interior that never appears in flight — and Activate this variant makes it the one the part is created with, from the browser, with an undo (it takes effect next time you start KSP).
- Apply with backup & undo — one button writes a ModuleManager patch to
GameData/IVAForge/patches/. Every write is backed up first; undo from the toast, or revert everything later. Optionally launches KSP for you. .ivalayoutsharing — export a cabin layout as a small JSON file (like a.craft), share it on the forum, import someone else's. No assets inside — only references by prop name, with a report of which mods you are missing.- Share your whole setup — one file with the interior each part loads, your calibrations, your cabin layouts and your favourites, plus the mods it needs and the version you have. Importing it shows a report first (missing mods, different versions, your own edits that would be replaced), applies only what differs, and has a clean undo. Format: docs/setup-format.md.
- Favourites — a star next to any cabin marks the ones you actually work on. It changes nothing in the game and it travels inside the shared setup file.
- i18n (English / Spanish) — full UI and messages, switchable in the app. English is the base and fallback.
- 100% local, no network access — everything runs on
127.0.0.1; the tool never phones home. Nothing you edit leaves your machine.
Everything you see is generated from YOUR install. IVA Forge ships only its own code and
calibration data — no meshes, no textures, no cockpit .cfgs from Squad or any mod. The first
time you run it, it bakes the catalog by reading the GameData you already own. Nothing from
Squad, ASET, RPM, MAS, SSPX or any other mod is included in the download or the repository. This
keeps the tool legal and respects the licenses of the props it renders.
- Windows. (Linux/macOS are not supported in v1 — the pipeline uses Windows paths and APIs. Ask if you want them.)
- Kerbal Space Program 1.12.x. This is the final KSP 1 release; no other version is targeted.
- ModuleManager installed in your GameData. IVA Forge writes MM patches; it does not bundle ModuleManager — install it from its thread or via CKAN. The tool detects it and warns if it is missing.
- Disk space: ~1.5 GB free where you unzip it. The tool itself is small, but the catalog it bakes
from your install is not: about 1 GB for a typical modded GameData (cabin bundles, the shared
texture atlas and the prop library), all of it under
catalog/and deletable at any time — it is regenerated on demand. - No Python needed. The release ships its own embedded Python runtime (bundled in the zip,
under
runtime/), so double-clickingIVAForge.batjust works — nothing to install, no terminal. Running from source (developers/contributors) is the only path that needs your own Python 3 +pip install -r requirements.txt— see Running from source.
- Download the latest release and unzip it anywhere (Documents, Desktop — not inside GameData). It
unpacks into a single folder of its own,
IVAForge-vX.Y.Z/. - Make sure ModuleManager is in your KSP GameData.
- That's it. There is no installer, and no Python to install — the runtime is inside the zip.
- Double-click
IVAForge.bat. It starts the local bridge (a minimized console window you can close to quit) and opens the catalog in your browser. You never touch a terminal. - First run: point it at KSP. If your install isn't auto-detected, a config page opens in the
browser — pick your KSP folder (the one that contains
GameData/andbuildID.txt, orbuildID64.txton Linux installs). - First bake. The tool bakes the catalog from your GameData with a progress bar ("N/M cabins · current · estimated time"), then bakes the prop library. Budget roughly 10-15 minutes and ~1 GB of disk for a typical modded install — it runs once, and later runs only re-bake what actually changed (seconds).
- Edit. Open a cabin, switch to editor mode, drag props onto the hull, tweak with the gizmos.
- Apply. Click Apply to game. IVA Forge backs up, writes the MM patch to
GameData/IVAForge/patches/, and shows a toast with an Undo button. Launch KSP (optionally from the same button) and check your IVA.
Contributors and anyone who prefers their own interpreter can skip the bundled runtime:
pip install -r requirements.txt # numpy, Pillow, matplotlib
python src/serve_catalog.py # start the bridge, then open http://127.0.0.1:8760/index.html
IVAForge.bat also falls back to your system Python automatically when no runtime/ folder is
present (developer checkout). To rebuild the shippable embedded runtime from python.org's official
embeddable package, run python packaging/make_runtime.py (Windows; downloads ~11 MB and installs
the deps into runtime/). The runtime/ folder is git-ignored — it is built, not committed.
Delete the folder GameData/IVAForge/ from your KSP install. That removes every patch IVA Forge
wrote; the original Squad/mod files were never modified. Your backups live in the tool's own
backups/ folder (outside GameData) and are never deleted automatically — remove them by hand if
you want. To remove the tool itself, delete the IVAForge-vX.Y.Z/ folder the download unpacked into.
- KSP not detected → the browser opens a config page. Enter the KSP folder that contains
GameData/andbuildID.txt(orbuildID64.txt). It's saved for next time. - A cabin shows "unsupported" → its bake failed (an unusual shader or texture format in that
mod). The catalog keeps working; that one cabin is skipped. The full error is in
catalog/bake_log.txt— please open an issue and attach it (see Contributing). - A cabin is marked
⚠ out of date→ its baked data is older than the current generator or than its own source files (a partial or interrupted bake). The red bar at the top counts them and tells you how to fix it: re-bake. If the badge survives a re-bake, it is your browser's cache — reload withCtrl+F5. - "ModuleManager not found" warning → install ModuleManager in GameData and re-bake.
- The bridge window closed / port busy → close any leftover minimized "IVA Forge" console and
double-click
IVAForge.batagain.
Thanks for helping. There are four low-friction ways to contribute that don't require touching the tool's code: calibration data, prop-face corrections, translations, and unsupported-cabin reports. Code PRs are welcome too — be honest about the modlist you tested against so issues can be reproduced.
The code is GPLv3; the calibration data is CC-BY-4.0. By contributing you agree your contribution ships under the same license as the part of the project it lands in.
Calibration data tells the viewer how to place and orient a cabin's exterior hull and its skin texture so the interior renders correctly. These 95 tuned cabins are the project's shared asset, and they live as versioned JSON — you can contribute one without touching any code.
The tool writes the file for you. You do not have to hand-write JSON:
- Calibrate a cabin in the viewer with the usual controls (hull orientation / scale / position, skin texture). Every click is remembered in your browser, cabin by cabin.
- Go back to the catalog (the page that lists mods and parts). A blue contribute bar appears at the top as soon as you have something to send, and it tells you how much: "You have 3 calibration(s) that this catalog does NOT ship yet, from 1 mod(s)." Type your nick there once — the data ships under CC-BY-4.0, so it needs attribution. It's remembered and lands in the file (and in the credits).
- Export the whole mod — each mod you have calibrated shows a
3 to sendbadge next to its name and anexport calibrationsbutton, so you calibrate 12 Bluedog cabins and send one file, not twelve — or one cabin, from its own row in the catalog and from the viewer's Contribute calibration block, right after tuning it. If a mod or cabin has nothing calibrated in your browser, no button is drawn: there is nothing to send. - The counter only asks for what is still missing. Once a maintainer merges your calibration and you
update, the value the catalog bakes matches yours and that cabin stops counting — the badge turns into
a quiet
N already included. (The catalog knows because every bake publishes its effective calibration per cabin inmanifest.js.) When the values differ, the bar names the cabin and shows both, yours and the catalog's, so you can judge before sending. The newer value wins: if the catalog took in a different value after you calibrated that cabin — one you never got to see — nothing is asked, the cabin is markedsuperseded by the catalogand your measurement is kept. What is asked about is the opposite case: you saw the catalog's value and changed it deliberately. That is a real conflict, it is named, and akeep the catalog'sbutton lets you drop your own note instead. - Drop the file into
calibrations/to use it immediately, and attach it to an issue or pull request so it ships with the next release.
Both routes produce exactly the same file for the same data (they share one code path), and the export
lives in localStorage, so it is per-browser and per-origin: what you calibrate opening
index.html directly (file://) is not the same store as what you calibrate through the local server
(http://127.0.0.1). Export before switching.
Only what you actually adjusted is exported. A cabin is included only if you pressed a calibration control in it — opening it, looking at it or flying around inside does not count. Within a cabin, only the field groups you touched are emitted, and a value that is the default and was already the default is dropped as a no-op. Reason: an entry full of default values would claim that somebody checked that cabin and found it fine. Nobody did, and that false entry would be treated as verified forever. A missing cabin is recoverable; a fabricated one is not.
The exported numbers come from the same code path as the on-screen readouts, and the button
validates the schema (types, ranges, legal 90° steps and texture letters) before the download — and
again on the serialized text — so a hull_scale: "1.02" fails on your screen instead of on someone
else's bake.
calibrations/ holds one .json per source mod (e.g. squad.json,
nearfuturespacecraft.json). That's the natural unit of contribution: whoever calibrates a mod's
cabins edits a single file. The loader reads all .json files in the directory, in alphabetical
order, and the last file that defines a field wins — so the filename matters:
| Filename | What it is | Rule |
|---|---|---|
<mod>.json |
Canonical repo file | One mod, one file. Two canonical files defining the same field of the same INTERNAL is a collision and is reported as an error. |
zz-contrib-<mod>[-<internal>]-<nick>.json |
Contribution (what the export button produces) | The zz- prefix sorts last, so it deliberately overrides the bundled data — you can test a calibration somebody sent you without editing anything. Every field it overrides is reported. |
Audit the directory with python src/build_catalog.py --check-calib (collisions, schema, missing
mods; exit code 2 if anything is wrong). A normal bake prints the same report but never aborts.
The exported file also declares which mod its cabins come from (required_mods, same pattern as
.ivalayout). Without that mod installed the file is inert: its keys are INTERNAL names that don't
exist in that GameData, so nothing matches — no effect, no error, no polluted catalog. The mod version
is recorded when available, so it's visible when a mod re-exports its models and the calibration goes
stale.
Each file is:
The key of each cabin is its INTERNAL name (the cabin id). Every field is optional — a cabin lists only what it needs; anything missing uses the sane default. Common fields:
| Field | Meaning |
|---|---|
hull_orient |
Extra 90° steps (X+ X- Y+ Y- Z+ Z-) on top of the base orientation, for hulls that still come out rotated. Most cabins need none. |
hull_recenter |
Re-center the hull on the interior skin's centroid. |
hull_scale |
Scale the hull to swallow interior-liner corners that poke through. |
hull_offset |
[x,y,z] position nudge, in metres, applied last. |
cam_up |
Force the camera "up" when the seat-derived heuristic fails. |
deploy_clip |
Name of the deploy animation clip for expandable habitats. |
skin_hide_mesh |
Skin transforms to hide (packed-state geometry). |
skin_uv_xform |
Skin texture orientation (A–I; A = identity). |
note |
Provenance — why you chose these values. Informational. |
All axes are scene axes (Z already mirrored), in metres. A full field reference lives in calibrations/README.md.
Format version. _format is ivaforge-calibration/2. Files written for /1 are migrated
automatically when loaded (/1 assumed the part-to-interior base rotation was Rx(-90), so every
cabin had to patch KSP's extra 180° spin by hand; /2 puts that spin in the base, where it belongs).
The migration is a pure re-expression: same hull, same pose. Cabins that had no hull_orient are
left alone on purpose — a missing field means "nobody checked", not "checked, nothing needed".
cam_up, deploy_clip, skin_hide_mesh and skin_xf_live have no live control, so they can only be
written by hand. In that case: add or edit the cabin's entry (by its INTERNAL name) in the matching
<mod>.json, fill only the fields you need, add a note explaining the values, and open a PR with
just the data — no code changes.
The loader degrades gracefully: a missing directory or a corrupt file emits a warning and is skipped (those cabins fall back to default behaviour), never a crash.
When you drag a prop in, IVA Forge turns its useful face — screen, buttons, printed labels — towards you. It works that out from the prop's own config: the screen transform of an RPM/MAS monitor, or the transform of its label, because the text is painted on the side you are meant to read. About a third of the library declares neither, and for those the tool has to guess.
When a prop comes in backwards, the fix belongs in propfaces/, and it is data, not code:
{
"_format": "ivaforge-propfaces/1",
"props": {
"ALCORFoodStation": { "face": "-Z", "up": "+Y", "note": "checked in the editor, both sides" }
}
}face is the axis that must point at the viewer (+X … -Z); up is optional and only needed if
the prop also comes in sideways. Every *.json in the folder is read in alphabetical order and
later files win field by field, so you can keep your own next to the shipped ones without editing
them. Full reference and the rules in propfaces/README.md.
An entry is a statement that somebody looked. Never fill it in from a hunch: a listed prop ignores the evidence its config actually had, so a wrong entry is worse than no entry. A prop nobody has checked keeps the old behaviour rather than being flipped on a guess. Editing this folder re-bakes only the props you touched, in about a second — cabins are not re-baked.
The UI and messages are driven by one pair of dictionaries: locales/en.json (the base and
fallback) and locales/es.json. To add a language:
-
Copy
locales/en.jsontolocales/<code>.json(e.g.de.json,fr.json). -
Translate the values. Do not change the keys. Leave technical game names, prop/part identifiers, and machine/protocol strings untranslated — they are identifiers, not prose.
-
Keep parity: every language must have exactly the same keys as English. Run the parity check and make sure it passes:
python src/i18n.pyIt prints the key count per language and fails if the sets differ.
-
Open a PR with the new locale file (and the parity check green).
English remains the fallback: any key you leave untranslated shows the English text rather than a blank.
If a cabin bakes as unsupported, the pipeline hit a shader or texture format it didn't expect in that mod. That's a bug worth reporting:
- Reproduce the bake (or just open the index — the cabin has an "unsupported" badge with a tooltip).
- Grab
catalog/bake_log.txt— it has the full traceback for the failed cabin. - Open an issue with: the mod and cabin name, your KSP version, and the relevant slice of the bake log attached. Mention any unusual texture/shader mods in your GameData.
These reports are how the pipeline learns to handle GameData combinations beyond the ones already tested.
Touching the viewer's code invalidates every cabin, so a one-line change means a full re-bake (~9 minutes on a typical modded install) before you can look at it. The working set cuts that to seconds:
python src/build_catalog.py --work <internal>[,<internal>...] # from now on, bake only these
python src/build_catalog.py --work-add <internal>[,...] # add to the set and bake
python src/build_catalog.py --work-show # what is in the set (does not bake)
python src/build_catalog.py --work-clear # drop it (next bake is full again)
python src/build_catalog.py --all # one-off full bake, set untouched
With three cabins in the set the edit-look cycle is about 30 seconds. The set is deliberately
loud about what it skips: every cabin it leaves behind is flagged ⚠ out of date in the index,
so a partially baked catalog can never be mistaken for a complete one. Clear the set before
measuring anything about the catalog as a whole.
Both READMEs are one document in two languages: any change here goes into README.es.md in the same commit.
- Code: GPLv3. Distributed forks must stay open — consistent with the IVA niche (ModuleManager, RPM and FreeIVA are GPL). The full license text ships in the download.
- Calibration data (
calibrations/): CC-BY-4.0. Open data with attribution; contribute yours by PR. - Bundled third party: three.js r128, MIT. The 3D renderer behind the
viewer, shipped unmodified in
vendor/three.min.js(its license header travels inside the file) and copied into the baked catalog at build time.
Built for the KSP IVA-modding community. Calibration data for 95 cabins across Squad, Making History, Near Future Spacecraft, SSPX and KPBS is the shared asset of the project — see Contributing to calibrate a cabin, add a language, or report an unsupported cabin. Bug reports and PRs welcome; be honest about your modlist so we can reproduce.
Calibrating a cabin takes two clicks to export: the tool writes the data file for you. The catalog shows how many cabins of each mod you have calibrated and exports them all in one file from the mod row (single cabins export from their own row, or from the viewer right after tuning them), with your nick in it. Send it in and it ships with the next release.
| Nick | Mods calibrated |
|---|---|
| LetalDark | Squad, SquadExpansion (Making History), Near Future Spacecraft, SSPX, KPBS |
(Send a calibration and your nick goes here — that's the attribution CC-BY-4.0 asks for.)
See docs/user-guide.md for the full workflow,
docs/ivalayout-format.md for the .ivalayout spec and
docs/setup-format.md for the shared-setup package.




{ "_format": "ivaforge-calibration/2", "_mod": "SquadExpansion", "_mod_label": "Making History", "_license": "CC-BY-4.0", "cabins": { "<INTERNAL name>": { "hull_orient": ["Z+"], "hull_recenter": true, "hull_scale": 1.126, "hull_offset": [-0.08, 0.0, 0.04], "cam_up": [0.0, 0.0, 1.0], "note": "why this was calibrated this way" } } }