INI

Working with INI

INI is the oldest config format still in daily use and the only one here with no specification at all. Everything else follows from that.

Nothing defines INI. There is no RFC, no working group, no reference grammar — a gap worth appreciating next to RFC 8259 for JSON or the versioned specification behind TOML. What INI has instead is an ancestor: Windows 3.x stored settings in .ini files and read them through GetPrivateProfileString, whose behaviour became the closest thing to a standard by being the only implementation anyone could check against. Every language that came afterwards reimplemented it from memory.

The result is a format whose rules are decided by whichever library you happened to install. Python's configparser lowercases every key, performs % interpolation on values, and raises on a repeated key. Node's ini package preserves key case, treats % as an ordinary character, and lets the last duplicate quietly win. Neither is wrong. There is nothing for either to be wrong about.

That vagueness never stopped anyone, because INI is genuinely pleasant to write and read. It is still what php.ini, tox.ini, setup.cfg, pip.conf and my.cnf use. Git stores your identity in it. systemd unit files are a dialect of it with their own additions, and EditorConfig picked it in 2011 for a brand-new format because a section header and a key are obvious to everyone.

The practical consequence is that an INI file is only as portable as the assumptions shared by the programs reading it — and those assumptions are exactly what nobody writes down. If you have one open and want to know what it says to a strict reader, INI Validator reports the duplicate keys and repeated sections that most parsers resolve without telling you, and INI to JSON shows the structure a program actually receives.

INI articles

INI tools on this site

All categories