Live data from Hacker News

Stop writing CLI validation. Parse it right the first time

hackers.pub

101–110 of 169 posts

Re: Stop writing CLI validation. Parse it right the first time

#101
Exactly the opposite of this. We should parse the command-line using _no_ strict types. Not even integers. Nothing beyond parsing its structure, e.g. which option names get which (string) values, and which flags are enabled. This can be done without knowing _anything_ about the application domain, and provide a generic options structure which is no longer a sequence of characters.

This approach IMNSHO is much cleaner than the intrication of cmdline parser libraries with application logic and application-domain-related types.

Then one can specify validation logic declaratively, and apply it generically.

This has the added benefit - for compiled rather than interpreted library - of not having to recompile the CLI parsing library for each different app and each different definition of options.

Re: Stop writing CLI validation. Parse it right the first time

#102
post #57

I like this advice, and yeah, I always try to make illegal states unrepresentable, possibly even to a fault. The problem I run into here is - how do you create good error messages when you do this? If the user has passed you input with multiple problems, how do you build a list of everything that's wrong with it if the parser crashes out halfway through?

I think you're looking at it too literally - what people usually mean with"making invalid state unrepresentable" is in the main application which has your domain code - which should be separate from your inputs He even gives the example of zod, which is a validation library he defines to be a parser. What he wants to say : "I don't want to write my own validation in a CLI, give me a good API already that first valida…

> I don't want to write my own validation in a CLI, give me a good API already that first validates and then converts the inputs into my declared schema

But that _is_ parsing, at least in the sense of "parse, don't validate". It's about turning inputs into real objects representing the domain code that you're about to be working with. The result is still going to be a DTO of some description, but it will be a DTO with guaranteed invariants that are useful to you. For example, a post request shouldn't be parsed into a user object just because it shares a lot of fields in common with a user. Instead it should become a DTO with the invariants fulfilled that makes sense for a DTO. Some of those invariants are simple (like "dates should be valid" -> the DTO contains Date objects not strings), and some will be more complex like the "if the server is active, then the port also needs to be provided" restriction from the article.

This is one of the key ideas behind Zod - it isn't just trying to validate whether an object matches a certain schema, but it converts the result into a type that accurately expresses the invariants that must be in place if the object is valid.

Re: Stop writing CLI validation. Parse it right the first time

#103

Exactly the opposite of this. We should parse the command-line using _no_ strict types. Not even integers. Nothing beyond parsing its structure, e.g. which option names get which (string) values, and which flags are enabled. This can be done without knowing _anything_ about the application domain, and provide a generic options structure which is no longer a sequence of characters. This approach IMNSHO is much cleaner…

Can you give some examples of this working well? It certainly goes against all of my experience working with CLIs and with parsing inputs in general (e.g. web APIs etc). In general, I've found that the quicker I can convert strings into rich types, the easier that code is to work with and the less likely I am to have troubles with invalid data.

Re: Stop writing CLI validation. Parse it right the first time

#104
post #102
post #57

Earlier quoted context omitted.

I think you're looking at it too literally - what people usually mean with"making invalid state unrepresentable" is in the main application which has your domain code - which should be separate from your inputs He even gives the example of zod, which is a validation library he defines to be a parser. What he wants to say : "I don't want to write my own validation in a CLI, give me a good API already that first valida…

> I don't want to write my own validation in a CLI, give me a good API already that first validates and then converts the inputs into my declared schema But that _is_ parsing, at least in the sense of "parse, don't validate". It's about turning inputs into real objects representing the domain code that you're about to be working with. The result is still going to be a DTO of some description, but it will be a DTO wit…

I dont disagree with the desire to get a good API like that. I was just pointing out that this was the core of the desire the author had, as 12_throw_away was correctly pointing out that _true_ parsing and making invalid state unrepresentable forces you to error out on the first missmatch, which makes it impossible to raise multiple issues. the only way around that is to allow invalid state during the input phase.

zod also allows invalid state as input, then attempts to shoehorn them into the desired schema, which still runs these validations the author was complaining about - just not in the code he wrote.

Re: Stop writing CLI validation. Parse it right the first time

#105

Rust with Clap solved this forever ago. Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool.

Almost every command line tool has runtime dependencies that must be installed on your system. $ ldd /usr/bin/rg linux-vdso.so.1 (0x00007fff45dd7000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x000070764e7b1000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000070764e6ca000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000070764de00000) /lib64/ld-linux-x86-64.so.2 (0x000070764e7e6000) The worst is co…

That’s the first rule anyone writing portable binaries learns. Compile against an old libc, and stuff tends to just work.

Re: Stop writing CLI validation. Parse it right the first time

#106

Rust with Clap solved this forever ago. Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool.

I will keep writing my CLI programs in the languages I want, thanks. Have it crossed your mind that these programs might be for yourself or for internal consumption? When you know runtime will be installed anyway?

That's fine, I'll be avoiding using them :)

Re: Stop writing CLI validation. Parse it right the first time

#107

Rust with Clap solved this forever ago. Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool.

Almost every command line tool has runtime dependencies that must be installed on your system. $ ldd /usr/bin/rg linux-vdso.so.1 (0x00007fff45dd7000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x000070764e7b1000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000070764e6ca000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000070764de00000) /lib64/ld-linux-x86-64.so.2 (0x000070764e7e6000) The worst is co…

Yes but I've never had a native tool fail on a missing libc. I've had several Python tools and JS tools fail on missing the right version of their interpreter. Even on the right interpreter version Python tools frequently shit the bed because they're so fragile.

Re: Stop writing CLI validation. Parse it right the first time

#108
post #105

Earlier quoted context omitted.

Almost every command line tool has runtime dependencies that must be installed on your system. $ ldd /usr/bin/rg linux-vdso.so.1 (0x00007fff45dd7000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x000070764e7b1000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000070764e6ca000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000070764de00000) /lib64/ld-linux-x86-64.so.2 (0x000070764e7e6000) The worst is co…

That’s the first rule anyone writing portable binaries learns. Compile against an old libc, and stuff tends to just work.

> Compile against an old libc

This clause is abstracting away a ton of work. If you want to compile the latest LLVM and get 'portable C++26', you need to bootstrap everything, including CMake from that old-hat libc on some ancient distro like CentOS 6 or Ubuntu 12.04.

I've said it before, I'll say it again: the Linux kernel may maintain ABI compatibility, but the fact that GNU libc breaks it anyway makes it a moot point. It is a pain to target older Linux with a newer distro, which is by far the most common development use case.

Re: Stop writing CLI validation. Parse it right the first time

#109

Rust with Clap solved this forever ago. Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool.

Almost every command line tool has runtime dependencies that must be installed on your system. $ ldd /usr/bin/rg linux-vdso.so.1 (0x00007fff45dd7000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x000070764e7b1000) libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x000070764e6ca000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x000070764de00000) /lib64/ld-linux-x86-64.so.2 (0x000070764e7e6000) The worst is co…

I statically link all my Linux CLI tools against musl for this reason. Or use Nix.

Re: Stop writing CLI validation. Parse it right the first time

#110
post #96

Rust with Clap solved this forever ago. Also - don't write CLI programs in languages that don't compile to native binaries. I don't want to have to drag around your runtime just to execute a command line tool.

Apparently that ship has sailed. Claude Code and Gemini CLI requires Node.js installation, and Gemini README reads as if npm is a tool that everybody knows and has already installed. https://www.anthropic.com/claude-code https://github.com/google-gemini/gemini-cli

That's terrible, but at the very least there's the tiny justification that those are web API clients rather than standalone/local tools.
Post reply on HN