Rendered at 12:16:17 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
layer8 15 hours ago [-]
> what you see is what you get: […] '10.20' and 10.20 are a string and a float, exactly as written.
This seems both underspecified and incorrect. Assuming a single-precision binary IEEE 754 floating-point number, 10.20 is actually 10.19999980926513671875. With double precision, it would be 10.199999999999999289457264239899814128875732421875. So what you see is not what you get, and it’s also unclear what exactly you’ll get.
Still strings and therefore fine for the SOML parser, but probably not a valid configuration in terms of the application-level types of the values. The syntax telling you the types is of limited utility as soon as the application schema has more specific ideas about the types than the configuration language.
mofle 14 hours ago [-]
> This seems both underspecified and incorrect.
"exactly as written" was wrong for the value. Only the type is. The spec already says a float is IEEE 754 binary64, same as JSON. Fixed the readme.
> Still strings and therefore fine for the SOML parser,
I have plans for some kind of schema support.
layer8 13 hours ago [-]
Schema support is the way to go, because applications will have a formal or informal schema no matter what, but then it’s better to drop most of the schemaless syntax rules in the first place. If someone wants `10.20` to mean the exact decimal value, or wants `30m` to mean “30 meters” instead of a duration, then that should be possible. Similarly, self-delimiting syntax like URLs shouldn’t require quotes.
mofle 13 hours ago [-]
[flagged]
qubex 14 hours ago [-]
#whatcouldpossiblygowrong
vbezhenar 15 hours ago [-]
Should be 0x1.466666p+3 for clarity.
supersimpleguy 15 hours ago [-]
[flagged]
lightandlight 17 hours ago [-]
Ironically the project seems LLM-generated.
I don't want to read Claude's interpretation of why your project matters. I want you to tell me directly.
mofle 14 hours ago [-]
It's created by a human, me. All decisions are human-made. I obviously used AI to help double-check all the work and improve the writing.
lightandlight 11 hours ago [-]
> All decisions are human-made
I believe you, but it's hard to tell when prose reads like something Claude generated.
LLMs make it so easy to blurt out hundreds of thousands of LOC with no effort. Too much to assess critically. So I've formed new heuristics for judging whether a project is worth my attention. One of those is LLM-flavoured prose, which I have come to view as a signal of low effort.
Zopieux 12 hours ago [-]
Yeah there claudisms are so off-putting is it crazy.
functionmouse 16 hours ago [-]
> your project
there's a very good chance there's no human involvement at all in this
dvirsky 15 hours ago [-]
The sole contributor has tons of repos and has been creating stuff on github for 15 years.
From the title, I thought this was a specification for configuring humans. I don't quite know what that means, and I'm disappointed still not to know.
VTimofeenko 16 hours ago [-]
Could probably compile it into CRISPR editing spec
tln 15 hours ago [-]
Feedback:
1. You should mention TOML in your first paragraph. "Why not TOML" exists at the end
2. how often are "instants"/dates really specified? Are you baking this in for TOML parity?
If you want leaner, drop this. If nothing else it's a lot of grammar.
If you want to lean in to "A value's type comes from its syntax", I'd suggest taking a cue from postgres and JS -- extensible literals. With JS tagged literals it would look like date`2026-09-19T14:00:00Z`. Conforming readers can fall back.
I'd use ver`3.1.0` 1000x more in config files than dates... I do like durations being baked in though.
Solid improvements over TOML and YAML.
nine_k 15 hours ago [-]
Instants are important if you migrate something, like TLS certificates, data flows, etc. ISO-8601 is widely adopted, unambiguously interpreted, human-friendly format for that. I see no reason to not have it.
tln 14 hours ago [-]
Is this format for data or for config?
The reason for not having is simply a matter of specification size. ISO-8601 is full of weirdness! SOML's date spec is reasonable looking but there is still a lot of nuance.
Having durations is nice and instants are highly complementary.
My feedback is just that if lots of literal formats are desired, maybe an extensible literal format!
nine_k 12 hours ago [-]
It's almost like there is another half of the language missing, the one which describes a schema to validate the config against.
benatkin 10 hours ago [-]
It's as much as a YAML fork as a TOML fork. I think each are emphasized the right amount.
mofle 14 hours ago [-]
Hey all. I'm the one working on this (a human). It's still early. It's something I have been wanting for many years, but I never had the time to invest in it until now.
Just want to balance the harsh (but useful) criticism here by saying thanks for pushing to try and make a better, more balanced alternative.
This is a space I have a tricky application for that's currently filled poorly by YAML, escaping regex is particularly painful. I will be watching with interest.
joshheitzman 16 hours ago [-]
From the comments here I can infer that it has a schema and in turn I can extrapolate that this is as much "for humans" as many other config formats that are deterministically parseable.
A GUI is a config format for humans as it can you show what all of the configuration options are along with text that tells you what they do. A GUI can also ensure that there are no invalid settings that are discovered separately from the edit session (sure it may not do so, but it has the possibility unlike whatever random text editor the user opens the config in).
ActionHank 15 hours ago [-]
Gotta be honest, any time there's a solution like there that makes it more "human" they've just removed the structure / syntax.
I'm guessing so you don't need to learn them, so then anyone off the street can edit the files, but it will break so bad without those guardrails, usually in some non-obvious way.
Leading us back to inventing some new "human" thing, but with more implicit rules, and the cycle continues.
econ 15 hours ago [-]
Have a text area that checks if the config is valid on each key stroke, if not rollback to the previous one. Can put some red ink under it explaining why you can't do that.
Trying to remove a required number the last remaining digit is highlighted so that you can type over it.
ActionHank 14 hours ago [-]
"Have a text area"
You've already failed. Config files are for more than just editing in an environment that you solely control.
nine_k 15 hours ago [-]
> just removed the structure / syntax.
But they added syntax, such as unit specifiers for time.
And some syntax, like YAML bare strings, or XML entities referring to external resources, has to be removed.
umvi 15 hours ago [-]
> durations like 30s are real values, so nobody has to guess the unit of timeout: 30
Pet peeve of mine, but I would argue that it's better to always keep units baked into the key.
If you have:
timeout_s: 30
Then unit information will never be lost, because the unit is always marshalled as a part of the key name and you don't have to worry if the target language has a duration type or not.
If you have:
timeout: 30s
Then unit information probably won't be lost, but could in the following scenarios:
- Target language doesn't have duration types (looking at the list - Ruby?)
- If you ever need to convert to/from a data format without durations like JSON
So basically you have to use SOML across your entire stack and always use languages that have native duration types, and also you have to be careful never to convert SOML to/from JSON (which is highly likely if you ever have to interface with external APIs). Do any of those things and you'll likely run into a unit confusion scenario at some point.
But there are going to be lots of configs that won't have native type like size. Again, just include units in key:
max_size_bytes: 30000000
In conclusion, my opinion is to KISS by including units in the key name and by sticking to bool/number/string primitives, hence why I almost always use JSON for everything (though if I could be granted one wish, it would be for JSON spec to allow for dangling commas)
vbezhenar 15 hours ago [-]
`timeout: 72h` reads better than `timeout_s: 6220800`
umvi 15 hours ago [-]
I agree, but there's a tradeoff which is that not every language/data format supports duration types:
Ruby:
config = SOML.load_file('config.soml', symbolize_names: true)
config[:timeout] # what are the units? uses SOML::Duration non-Ruby type
Even worse if you ever convert to/from JSON. My opinion is that config files should be as dumb and simple as possible. If you want humans to be able to read/write fancy stuff like "72h" for config, build a UI layer for the human to use in front of the config. Then they can click a little calendar icon to select the date. The backing config uses dumb iso 8601 string instead of a magical date type baked into the config language.
Yasuraka 15 hours ago [-]
> no key needs quotes
> 'the name': 'quotes are the escape hatch, when a key needs spaces'
To quote David Fincher:
> They know you have computers and can show a Tyrannosaurus Rex eat a car, so they know you can do anything. The question is: what don't you do, not what do you do.
Constraints liberate; I wish people tended to more strictness. I had plenty of stumbling over "features", asking myself who couldve ever needed them. This particular one also irked me about CUE.
But that's just a nit.
walthamstow 15 hours ago [-]
Love the Fincher quote. That escape hatch thing is such a Claudism.
yegle 14 hours ago [-]
Genuine question for TOML (or any config DSL that don't support inheritance) users: what's the advantage compared to text protobuf configs?
To me being able to do some templating/inheritance to generate slightly different config (or deviating from the standard/default config) seems to be vital as a config DSL. In that regard, even YAML is superior with its half-ass anchor thingy.
catlifeonmars 16 hours ago [-]
There are numerous inaccuracies in the “Why not TOML” section of the README. Here are a few:
> CVE-2026-44244 injected a [core] section into .git/config for code execution.
Git config is not TOML. It’s an ini-based bespoke syntax
> SOML needs quotes for a literal dot.
So does TOML, the dot notation is for nested keys. You use quotes for a literal dot.
——
FWIW I like the decision to have a first class duration type.
mofle 14 hours ago [-]
Git config indeed isn't TOML, but it's the same trick; a newline adds a section header in any line-oriented config.
TOML needs quotes too. But if you forget them, TOML nests silently, while SOML errors.
I have updated the readme to make these things more clear.
catlifeonmars 12 hours ago [-]
Respectfully, the fact that you copypasted LLM output here to respond does not instill much confidence that you know what you are doing.
priomsrb 16 hours ago [-]
Looks nice!
It would be great if you had a simple website that allowed you to enter SOML and see the JSON side-by-side (similar to typescript playground https://www.typescriptlang.org/play/).
mofle 14 hours ago [-]
This is definitely planned.
andyferris 14 hours ago [-]
I get some of this... but the argument around versions like 3.10 being footguns in YAML apply here too - in both YAML and SOML both you want to quote that as a string. (I suppose in SOML the user might be used to quoting strings, but in both cases you'd still want your application-level parser to reject floats for that field for safety's sake).
yoyohello13 15 hours ago [-]
Isn't every configuration format made for humans? In fact, every programming language was made for humans.
ModernMech 15 hours ago [-]
In a reductive sense, yes. But practically, sometimes design considerations are made so the language is easier to parse or implement, which at the same time make it harder for humans to parse and understand. When someone says it's "made for humans" they mean they decided to make it easier for humans to read and write, often with the tradeoff that the parser and compiler will be more complicated.
I found out about this format because of PowerShell DSC (the Microsoft equivalent of Ansible). The format itself is very neat, but the `Import-PowerShellDataFile` cmdlet is absolutely unhelpful at showing you where the error is if it cannot parse the PSD1 file.
sedatk 14 hours ago [-]
Ouch. I'm surprised that it's still the case after so many years.
sn0n 13 hours ago [-]
Seems inconsistent…
Also the glaring: Error in user YAML: (<unknown>): did not find expected ',' or '}' while parsing a flow mapping at line 10 column 10
CodesInChaos 17 hours ago [-]
What I'm missing:
1. The readme doesn't make it clear what its "float" type is. A double, a decimal, implementation defined. I'm generally not a fan of restricting numbers to what a double can represent, like toml does.
2. It doesn't have a good way to model key-value pair like types such as tagged unions, polymorphic types, or function invocations. Simply allowing a key-value pair as a value (right associative) where the key is a string matching the keys of an object would fix this. Alternatively a function call syntax would fix this, which would also enable tuples as a concept distinct from arrays.
mofle 14 hours ago [-]
1. It's in the spec. It's a binary64 double.
2. These are schema and app concerns. Schema is something I plan to tackle.
CodesInChaos 12 hours ago [-]
> These are schema and app concerns
Discriminators are one of the fundamental building blocks of composition (sum types in ADT parlance). The workarounds for expressing them are verbose, ugly, and complicate schemas.
Consider `shape: circle: { radius : 1}` vs the workarounds like `shape: { type: circle, radius: 1}` or `shape: { circle: { radius: 1 }`.
bjacobso 16 hours ago [-]
The tagged-union / function-call point is where I keep ending up too. Once a config needs “one of these shapes” or “this thing with these arguments”, data formats grow conventions on top (type: keys, YAML !tags, $ref), and every consumer reimplements them.
I’ve been building Forma (https://forma-lang.com), a small typed Lisp aimed at that zone. Everything is (head args...), so a tagged value and a call are the same syntax, and you declare the vocabulary yourself:
job and backoff are forms you define with typed holes. The checker reports errors at the line you wrote, even after macro expansion. The output is plain JSON (or generated Effect TypeScript, but could target any language), so the app reading it doesn’t embed the language.
ryanschaefer 12 hours ago [-]
Did we learn nothing from TOON…?
yardstick 13 hours ago [-]
Can a key be a URL?
jll29 17 hours ago [-]
Looks like Windows *.ini format except ":" instead of "="...
CodesInChaos 17 hours ago [-]
Not really. INI has a fixed structure (section>key>value) and its values are untyped.
So a stripped down variant of cue? Why not use cue directly?
brianm 17 hours ago [-]
Cue only really exists in go, and has a dependency chain to make maven weep.
I think cue is better thought of as a language you use to generate JSON (or yaml, or, let's be honest, k8s flavored yaml) configs rather than a config language you use in your app.
mgantlett 17 hours ago [-]
[flagged]
petre 16 hours ago [-]
We already have TOML and it's great. I can seamlessly upgrade from ini to toml.
catlifeonmars 16 hours ago [-]
TOML is probably my go-to these days.
I think where TOML shines is when your configuration schema is relatively flat and simple. If you want to heavily nest configuration it can quickly get difficult to read. I’d love a more limited version of TOML that restricts the nesting depth.
microflash 16 hours ago [-]
There's a comparison [0] where some differences are explained.
This seems both underspecified and incorrect. Assuming a single-precision binary IEEE 754 floating-point number, 10.20 is actually 10.19999980926513671875. With double precision, it would be 10.199999999999999289457264239899814128875732421875. So what you see is not what you get, and it’s also unclear what exactly you’ll get.
> A value's type comes from its syntax, never from its content […] allowed-origins: [ 'https://example.com' 'https://example.org' ]
This looks like URLs, but are strings. What if you had:
> allowed-origins: [ 'httpș://example.com' 'ħttps://example.org' ]
Still strings and therefore fine for the SOML parser, but probably not a valid configuration in terms of the application-level types of the values. The syntax telling you the types is of limited utility as soon as the application schema has more specific ideas about the types than the configuration language.
"exactly as written" was wrong for the value. Only the type is. The spec already says a float is IEEE 754 binary64, same as JSON. Fixed the readme.
> Still strings and therefore fine for the SOML parser,
I have plans for some kind of schema support.
I don't want to read Claude's interpretation of why your project matters. I want you to tell me directly.
I believe you, but it's hard to tell when prose reads like something Claude generated.
LLMs make it so easy to blurt out hundreds of thousands of LOC with no effort. Too much to assess critically. So I've formed new heuristics for judging whether a project is worth my attention. One of those is LLM-flavoured prose, which I have come to view as a signal of low effort.
there's a very good chance there's no human involvement at all in this
They look like a human to me.
1. You should mention TOML in your first paragraph. "Why not TOML" exists at the end
2. how often are "instants"/dates really specified? Are you baking this in for TOML parity?
If you want leaner, drop this. If nothing else it's a lot of grammar.
If you want to lean in to "A value's type comes from its syntax", I'd suggest taking a cue from postgres and JS -- extensible literals. With JS tagged literals it would look like date`2026-09-19T14:00:00Z`. Conforming readers can fall back.
I'd use ver`3.1.0` 1000x more in config files than dates... I do like durations being baked in though.
Solid improvements over TOML and YAML.
The reason for not having is simply a matter of specification size. ISO-8601 is full of weirdness! SOML's date spec is reasonable looking but there is still a lot of nuance.
Having durations is nice and instants are highly complementary. My feedback is just that if lots of literal formats are desired, maybe an extensible literal format!
It's already powering the frontmatter of my website: https://github.com/sindresorhus/sindresorhus.github.com/blob...
This is a space I have a tricky application for that's currently filled poorly by YAML, escaping regex is particularly painful. I will be watching with interest.
A GUI is a config format for humans as it can you show what all of the configuration options are along with text that tells you what they do. A GUI can also ensure that there are no invalid settings that are discovered separately from the edit session (sure it may not do so, but it has the possibility unlike whatever random text editor the user opens the config in).
I'm guessing so you don't need to learn them, so then anyone off the street can edit the files, but it will break so bad without those guardrails, usually in some non-obvious way.
Leading us back to inventing some new "human" thing, but with more implicit rules, and the cycle continues.
Trying to remove a required number the last remaining digit is highlighted so that you can type over it.
You've already failed. Config files are for more than just editing in an environment that you solely control.
But they added syntax, such as unit specifiers for time.
And some syntax, like YAML bare strings, or XML entities referring to external resources, has to be removed.
Pet peeve of mine, but I would argue that it's better to always keep units baked into the key.
If you have:
Then unit information will never be lost, because the unit is always marshalled as a part of the key name and you don't have to worry if the target language has a duration type or not.If you have:
Then unit information probably won't be lost, but could in the following scenarios:- Target language doesn't have duration types (looking at the list - Ruby?)
- If you ever need to convert to/from a data format without durations like JSON
So basically you have to use SOML across your entire stack and always use languages that have native duration types, and also you have to be careful never to convert SOML to/from JSON (which is highly likely if you ever have to interface with external APIs). Do any of those things and you'll likely run into a unit confusion scenario at some point.
But there are going to be lots of configs that won't have native type like size. Again, just include units in key:
In conclusion, my opinion is to KISS by including units in the key name and by sticking to bool/number/string primitives, hence why I almost always use JSON for everything (though if I could be granted one wish, it would be for JSON spec to allow for dangling commas)Ruby:
Even worse if you ever convert to/from JSON. My opinion is that config files should be as dumb and simple as possible. If you want humans to be able to read/write fancy stuff like "72h" for config, build a UI layer for the human to use in front of the config. Then they can click a little calendar icon to select the date. The backing config uses dumb iso 8601 string instead of a magical date type baked into the config language.> 'the name': 'quotes are the escape hatch, when a key needs spaces'
To quote David Fincher:
> They know you have computers and can show a Tyrannosaurus Rex eat a car, so they know you can do anything. The question is: what don't you do, not what do you do.
Constraints liberate; I wish people tended to more strictness. I had plenty of stumbling over "features", asking myself who couldve ever needed them. This particular one also irked me about CUE.
But that's just a nit.
To me being able to do some templating/inheritance to generate slightly different config (or deviating from the standard/default config) seems to be vital as a config DSL. In that regard, even YAML is superior with its half-ass anchor thingy.
> CVE-2026-44244 injected a [core] section into .git/config for code execution.
Git config is not TOML. It’s an ini-based bespoke syntax
> SOML needs quotes for a literal dot.
So does TOML, the dot notation is for nested keys. You use quotes for a literal dot.
——
FWIW I like the decision to have a first class duration type.
TOML needs quotes too. But if you forget them, TOML nests silently, while SOML errors.
I have updated the readme to make these things more clear.
It would be great if you had a simple website that allowed you to enter SOML and see the JSON side-by-side (similar to typescript playground https://www.typescriptlang.org/play/).
Also the glaring: Error in user YAML: (<unknown>): did not find expected ',' or '}' while parsing a flow mapping at line 10 column 10
1. The readme doesn't make it clear what its "float" type is. A double, a decimal, implementation defined. I'm generally not a fan of restricting numbers to what a double can represent, like toml does.
2. It doesn't have a good way to model key-value pair like types such as tagged unions, polymorphic types, or function invocations. Simply allowing a key-value pair as a value (right associative) where the key is a string matching the keys of an object would fix this. Alternatively a function call syntax would fix this, which would also enable tuples as a concept distinct from arrays.
2. These are schema and app concerns. Schema is something I plan to tackle.
Discriminators are one of the fundamental building blocks of composition (sum types in ADT parlance). The workarounds for expressing them are verbose, ugly, and complicate schemas.
Consider `shape: circle: { radius : 1}` vs the workarounds like `shape: { type: circle, radius: 1}` or `shape: { circle: { radius: 1 }`.
I’ve been building Forma (https://forma-lang.com), a small typed Lisp aimed at that zone. Everything is (head args...), so a tagged value and a call are the same syntax, and you declare the vocabulary yourself:
job and backoff are forms you define with typed holes. The checker reports errors at the line you wrote, even after macro expansion. The output is plain JSON (or generated Effect TypeScript, but could target any language), so the app reading it doesn’t embed the language.1: https://huml.io/
I think cue is better thought of as a language you use to generate JSON (or yaml, or, let's be honest, k8s flavored yaml) configs rather than a config language you use in your app.
I think where TOML shines is when your configuration schema is relatively flat and simple. If you want to heavily nest configuration it can quickly get difficult to read. I’d love a more limited version of TOML that restricts the nesting depth.
[0]: https://github.com/soml-lang/soml/blob/main/comparison.md
[0]: https://github.com/soml-lang/soml/blob/main/schema.md
I'm curious for example configs that are top-level lists?
Or it could be a list of records:
{name: 'Alice', age: 42}
{name: 'Bob': age: 44}