The tomlet logomark: a folded golden omelette dotted with diced paprika

TOML + omelette · a tidy little parser for Gleam

TOML that
keeps your
comments.

tomlet parses TOML 1.0.0 into a document that remembers every comment, key order, and bit of whitespace. Edit a value, write it back, and the rest of the file comes out exactly how the human left it.

gleam add tomlet
See it round-trip ↓
config.toml in
# the user's favorite snack
snack = "tomato"  # raw, with salt
config.toml out
# the user's favorite snack
snack = "tomato sandwich"  # raw, with salt
comments preserved Only the value changed. Both comments stayed put.

parse(s) |> to_string == s

An unedited document writes back byte for byte. Comments, key order, string style, integer base, CRLF vs LF: all of it survives the round trip. No reformatting, no surprises in the diff.

// the whole point

Edit a value.
Leave the file alone.

In the BEAM world, most TOML libraries only read — and the rare one that can write hands you a freshly reformatted file with the comments gone. tomlet treats the surrounding text as sacred: it changes the bytes you asked for and nothing else.

before · gleam.toml toml
# package metadata
name = "tomlet"
version = 0
draft = true
three checked edits gleam
let doc = tomlet.set_int(doc, ["version"], 1)
let doc = tomlet.remove(doc, ["draft"])
let doc = tomlet.insert_comment_before(
        doc, ["version"], "first stable release")
after · gleam.toml toml
# package metadata
name = "tomlet"
# first stable release
version = 1

The package metadata header never moved, name is untouched, the new comment landed right where you asked, and draft is simply gone.

// what's folded in

Everything you'd want in a
round-tripping parser.

  • Lossless round-trip

    Parse and write back byte-for-byte. Whitespace, key order, string style and integer base are all preserved.

  • Edits keep their neighbours

    Setting a value rewrites only that value's text. Comments above and beside it are never disturbed.

  • Friendly typed access

    get_string, get_int, get_bool, get_date and friends, addressed by key path, with stable WrongType errors.

  • Checked edits, no panics

    Every edit returns a Result, so bad paths, key conflicts and forbidden comment characters are errors you handle, not crashes.

  • TOML 1.0.0, by the book

    Validated against the official toml-test suite, both the valid/ and invalid/ corpora.

  • Pure Gleam, both targets

    No NIFs, no native deps. Runs the same on Erlang and JavaScript, and parses raw bytes with UTF-8 and BOM validation.

// reading is just as tidy

Pull out the value
you came for.

Typed accessors take a key path and hand back exactly the type you asked for, including dates and times as opaque values with lexical *_to_string helpers. Mismatch a type and you get a clear, matchable error instead of a guess.

typed access gleam
let assert Ok(doc) = tomlet.parse(input)

let assert Ok(title)   = tomlet.get_string(doc, ["title"])
let assert Ok(version) = tomlet.get_int(doc, ["version"])
let assert Ok(enabled) = tomlet.get_bool(doc, ["enabled"])

# nested keys use the same path syntax
let assert Ok(name) = tomlet.get_string(doc, ["pkg", "name"])

// why it exists

The BEAM didn't have one.

No existing Erlang, Elixir or Gleam TOML library round-trips comments — they parse into plain maps and throw the comments away. Most can only read; the few that can write give you back a reformatted file. If you wanted to bump a version in gleam.toml or rewrite a pyproject.toml as a build step without nuking the author's notes, you were out of luck.

tomlet fills that gap. It's a fresh library with an AST built from the start for lossless round-trip, inspired by Rust's toml_edit and Python's tomlkit, now with a friendly Gleam accent.