TOML Syntax Cheat Sheet
Key-value pairs, tables, arrays, and data types for writing valid TOML configuration files like pyproject.toml and Cargo.toml.
Key-Value Pairs & Basic Types
The core scalar types TOML supports.
title = "My App"version = "1.4.0"port = 8080debug = falsepi = 3.14159created = 2026-03-12T10:00:00Z # RFC 3339 datetime, no quotestags = ["cli", "rust", "tool"] # arrayowners = ["alice", "bob"]
Tables & Nested Tables
Tables group related keys, like a JSON object under a name.
[package]name = "my-app"version = "1.4.0"edition = "2021"[package.metadata.docs]all-features = true[dependencies]serde = { version = "1.0", features = ["derive"] } # inline tabletokio = "1.38"
Array of Tables
Repeated `[[section]]` blocks produce an array of tables under that key.
[[bin]]name = "cli"path = "src/main.rs"[[bin]]name = "worker"path = "src/worker.rs"# Equivalent JSON: { "bin": [ {"name":"cli",...}, {"name":"worker",...} ] }
Type Reference
The data types TOML natively supports and how they're written.
- String- basic "double-quoted" (escapes) or 'single-quoted' (literal)
- Multi-line string- triple-quoted """...""", first newline after opener is trimmed
- Integer- 42, -17, 1_000_000 (underscores allowed as separators)
- Float- 3.14, 1e10, inf, nan
- Boolean- true / false, lowercase only
- Datetime- RFC 3339: offset, local datetime, local date, or local time
- Array- [1, 2, 3], can be multi-line, trailing comma allowed
String Escaping & Multi-line Strings
Basic vs literal strings, and how multi-line variants trim their opening newline.
# Basic string - backslash escapes applypath = "C:\\Users\\alice\\config"# Literal string - no escaping, WYSIWYG (great for regex/Windows paths)regex = 'C:\Users\*\config.toml'# Multi-line basic string - leading newline right after """ is trimmeddescription = """This is line one.This is line two."""# Multi-line literal - triple single-quotes, still no escapingscript = '''#!/bin/shecho "no \n escapes here"'''
Datetime Variants & Precision
TOML's four RFC 3339 datetime forms, from fully offset-aware to time-only.
offset_datetime = 2026-03-12T10:00:00-05:00 # RFC 3339 with explicit offsetutc_datetime = 2026-03-12T10:00:00Zlocal_datetime = 2026-03-12T10:00:00 # no offset - timezone-naivelocal_date = 2026-03-12local_time = 10:00:00precise = 2026-03-12T10:00:00.123456Z # fractional seconds, arbitrary precision
Dotted Keys vs Inline Tables
How implicit tables from dotted keys interact with explicit [header] tables.
# Dotted keys build an implicit table without a [header]server.host = "localhost"server.port = 8080# Equivalent to:# [server]# host = "localhost"# port = 8080# Inline tables must stay on a single line, no trailing comma before }point = { x = 1, y = 2 }# Once 'server' is opened via [header], you cannot reopen it with dotted keys[server]name = "web-1"# server.host = "x" <- illegal: 'server' is already a defined table
TOML v1.0 Spec Gotchas
Parser rules that trip people up coming from JSON or YAML.
- Key order doesn't matter- except array-of-tables entries, which are ordered by appearance
- Keys are case-sensitive and unique- redefining a key within the same table is a parse error
- Bare keys- only A-Z a-z 0-9 _ - ; anything else needs quoting, e.g. "my key" = 1
- Table declaration order- a sub-table like [a.b] must be declared after its parent [a], never before
- Comments- start with # and run to end of line; TOML has no block comment syntax
- Trailing commas- allowed in multi-line arrays, not allowed in inline tables
- Special floats- nan, +nan, -nan, inf, +inf, -inf are written unquoted
Real-World Build Config
How TOML structures a Cargo workspace and a Python build-system declaration in practice.
# Cargo workspace root[workspace]members = ["crates/*"]resolver = "2"[workspace.package]version = "2.3.0"edition = "2021"[workspace.dependencies]serde = { version = "1.0", features = ["derive"] }# pyproject.toml build backend declaration[build-system]requires = ["setuptools>=68", "wheel"]build-backend = "setuptools.build_meta"[project]name = "my-package"dynamic = ["version"]
Prefer dotted keys (`server.host = "localhost"`) over deeply nested `[server]` tables when you only have one or two fields — it keeps short configs like `pyproject.toml` snippets readable without an extra table header.