Rendered at 13:51:34 GMT+0000 (Coordinated Universal Time) with Cloudflare Workers.
jklowden 30 minutes ago [-]
Geez, what a lot of vague self-contradictory self-regarding opinionated advice.
Is terminal a world of “pure information’ or “a mess”? Both, it seems. Don’t dump “pages and pages of debug” text? Check. But do use boldface fonts “in a terminal independent way” and “try” to provide man pages. But because “some people” don’t know about them and “some platforms” don’t support them, provide help text by default.
Those “some” by the way are one: Windows. Do please enlighten us on the terminal-independent font control system that includes CMD.EXE.
How much is too much? Their showcase examples are more than 25 lines, more than the default size of a terminal window. The authors don’t give much weight to context, to the ability to look back on over the history of the interactive session. No, much better to splat the screen with 50 lines the user didn’t request, because helpful.
Oh, and don’t write a filter like cat(1). How the system is supposed to distinguish between reading from standard input and reading from standard input by mistake, they don’t say. Just quit and print a help message.
I have different advice: please don’t help. Please be quiet. Don’t suggest, don’t guess, dont offer, don’t assume. Just do. Do what the user said. If he wants something else, he’ll say so in time.
If you want —help to do something useful because you think your user is too dense to find the manual (condescension much?) then invoke it for him. Just maybe put a hint somewhere to press “q” to quit.
Virtually all the “help” I get on the command line is unasked-for and unwanted and unhelpful. If I fat-finger “ls”, I don’t need a suggestion to install lsof. The very last thing I want is 50 lines of noise obscuring what I was looking at before you so helpfully interrupted.
eikenberry 13 hours ago [-]
> Use a pager (e.g. less) if you are outputting a lot of text.
If I wanted to use a pager I'd pipe the output to a pager, no pipe to pager means I want it all dumped to STDOUT.
So annoying.
ventana 11 hours ago [-]
This is a common approach, CLI tools often use isatty [1] to check if the output fd is a TTY or not. Try running "git log" for example; if you have many commits, it will page through "less" or $PAGER only if it sees that you're on a real TTY; but if not, it will not. Try this:
git log # PAGER undefined; uses less
PAGER=/usr/bin/head git log # pages through head, you get 10 lines
PAGER= git log # PAGER is empty; does not page
git log | cat # output is not a TTY; does not page
(also, notice that git uses colors if the output is going to a terminal, and does not if not)
I don't think I was ever bothered by the automatic paging through "less".
I'm bothered by it because whatever git command that I'm executing will put its output in a pager and when I quit the pager it's not there anymore. I want the output on the screen when I start typing the next command. Oh my God, this is such a frustrating pattern.
simon-b 11 hours ago [-]
This is indeed an annoying, but solvable, less default. You can eg use `export LESS="-XF"` to change behaviour.
jpitz 15 minutes ago [-]
That's useful, although I don't know if I will enable it for generally or specifically for git.
asabla 6 hours ago [-]
It took me way too many years before I set this as a default in my profile files.
The funny thing is. I kept missing this detail every time I read through git. Feels like I was blind to the whole concept of it
Vingdoloras 6 hours ago [-]
I had the same issue specifically with git, for the same reason. You can configure git to not use a pager by setting core.pager to an empty string.
ventana 11 hours ago [-]
Then export PAGER= in your shell profile should help!
Ferret7446 9 hours ago [-]
Unfortunately not all programs respect an empty PAGER vs an unset PAGER. It's more reliable to use PAGER=cat
yjftsjthsd-h 10 hours ago [-]
Another example, which I find very annoying, is `systemctl status`; when the service has... either enough log lines or wide enough lines, idk, it will helpfully page them. So checking the status of a service randomly may or may not block your terminal. I cannot stress enough that I do not want to have to look at the screen and decide interactively whether or not I need to hit q before I can run another command.
inetknght 11 hours ago [-]
Yeah no. If I wanted to use a pager, I'd use a pager.
I want the output visible on screen after I exit the pager. If I didn't want it on screen, I'd pipe it to a file and open that in a text editor. That will disappear when I close the file. As a bonus: I can then use grep without having to repeat whatever command I used.
Even more importantly: I want the command to behave identically regardless of whether its stdin or stdout is /dev/null or a terminal or a socket or a serial port or a pipe or anything else that it can read or write with. Try writing a script when the tools themselves change how they behave whether they're running in a script or in a terminal or elsewhere. It kinda sucks.
ithkuil 7 hours ago [-]
You make a reasonable point so I don't want to oppose it but just to offer more tricks in case some of you don't know them:
_less_ has a nice "&" command that is like "/" (search) but that filters instead like grep.
You can also pipe to an external command from less
hulitu 9 hours ago [-]
> Try writing a script when the tools themselves change how they behave whether they're running in a script or in a terminal
But we smart coders. We think everything. Remind me later.
ventana 10 hours ago [-]
[dead]
eikenberry 7 hours ago [-]
Right. IMO this is bad behavior. I have `pager=cat` in my git config to deal with it there and several other aliases (include --no-pager) for systemd related stuff that do it to.
keithnz 13 hours ago [-]
100% - I want to use whatever pager I might prefer at the moment, this advice violates their core principle "you make programs that are modular enough to be recombined as needed"
oneeyedpigeon 3 hours ago [-]
I find it far more convenient for tools to take options to use a pager, rather than to having to manually type "| less" for every command that I want to behave nicely. Just behave nicely by default; if I want you to behave awkwardly, I'll let you know!
chriswarbo 57 minutes ago [-]
Define "nicely".
For example, many pagers don't work well when stdin is line-buffered (they assume they'll see individual key presses as they happen)
Pagers can also conflict with keys that the terminal emulator is using for a different purpose. This is especially annoying when the terminal emulator is using those keys for pager-like functionality in the first place!
An example of both of these is Emacs `shell-mode`.
(I personally set `PAGER=cat` in my Bash profile, which avoids most of these shenanigans)
kps 26 minutes ago [-]
Colour addendum: If the user hasn't configured anything, don't use a colour other than red without checking whether the terminal has a light or dark background. Don't hardcode colours.
hankbond 14 hours ago [-]
> Whatever software you’re building, you can be absolutely certain that people will use it in ways you didn’t anticipate. Your software will become a part in a larger system—your only choice is over whether it will be a well-behaved part.
For comfortable reading, I just had to figure out what on this webpage causes Chromium to drop subpixel rendering, and it's not this:
html { -webkit-font-smoothing: antialiased; }
it's this:
#TableOfContents { backdrop-filter: blur(3px); }
A panel that overlaps content only on narrow screens disables subpixel rendering for the entire text. Thanks Chromium. Not an issue on Firefox, btw.
ljwolf 3 hours ago [-]
Why is this high x-height serif-based typography taking over SF aesthetics now?
user3939382 50 minutes ago [-]
Check out Apple Garamond. What’s old is new.
atiedebee 7 hours ago [-]
> The concise help text should only include:
> - A description of what your program does.
> - One or two example invocations.
> - Descriptions of flags, unless there are lots of them.
> - An instruction to pass the --help flag for more information.
I disagree with this. The first 3 points should all unconditionally be in the man page of the program. In my ideal scenario, the jq short help message would omit everything after the "Usage" section except for the message to run the command with --help.
oneeyedpigeon 3 hours ago [-]
Yup, I agree. There seems to have been a trend recently to output a LOT on `cmd` (poor), even more on `cmd --help` (unpaged too: bad), and to not have a man page (terrible!). Every program should have a man page, a bare command should give usage (ideally, a single line), and --help should give a decent short overview (ideally less than a screen height or, failing that, automatically paged).
chriswarbo 55 minutes ago [-]
The Nix commands have a decent approach: passing `--help` will invoke `man` on the relevant manual (sub-commands tend to have individual man pages).
user3939382 49 minutes ago [-]
This is my design as well, didn’t realize Nix arrived at it. Help renders the man page.
jodrellblank 24 minutes ago [-]
It's awful UX for a program to know that you used it wrong, to be able to print the help there and then, and instead to tell you off and instruct you to ask politely (with --help). People who think that's okay in CLI world hate that kind of uppity-C3PO-servant behaviour from an LLM.
$ thing
usage: -lscekm4urytmvjpq9i8u3o54ernymctpwi8eruymgv
ah ah ah, <finger wag>, ask nicely for: --help
$ thing -h
ERROR! There is no option -h
What could you possibly want?
It's a mystery!
What if -h was rm -rf / did you even think of that?
Could have printed actual help here,
Filling up your screen with text anyway
and then you ask for --help and get five screens starting with "-a initialize line feed motor on electromechanical teletype output device from 1964" and on and on with options nobody uses mixed with the same priority amongst parameters everyone uses.
This is yet another area where GUI programs on Windows 98[1] were better than today's Linux state of the art: pressing F1 opening a separate window with HTML-based help with contents, colours, fonts, text styles, hyperlinks, tables, pictures, an index, a search, is so vastly superior that it's unbelievable[2] that here we are in 2026 and Linux world is still infighting over whether a pager is a sign of weakness and low status, or whether showing help by default is a sign of a low quality programmer, for a problem that was completely solved during the Clinton Administration! (And presumably solved in a similar way earlier by classic MacOS, earlier by Amiga OS, and earlier at Xerox PARC).
Having a single output stream and trying to do everything on it is just bad design. Having the program guess what you want, or a toggle to change between working and being informative, or an environment variable to trigger the toggle, are downstream problems that can never please everybody, to avoid facing the bad design and dealing with it.
> A command is saying too little when it hangs for several minutes and the user starts to wonder if it’s broken.
Nope. For debugging the program, it is nice to have some debug tracing option, but if it's not the program's specification to produce output, it should not produce any. If the program's specification is that it produces a certain output after a certain calculation, then it shall not produce any other output, even if that calculation takes three weeks.
"cp -r from to" is supposed to be quiet until it's done or hits an error.
It would be nice to have an agreed-upon protocol for progress reporting. For instance, imagine of we had file descriptor 3 as "stdprogress". Programs could dump specially formatted messages there which the parent job control shell could intercept and turn into a progress display (with multiple rows for pipeline elements and such). It's not bad; but fluff like this can't be in band with the output, or at least not by default.
procflora 14 hours ago [-]
Isn't this basically how more modern "chatty" CLIs use stderr? Put all the nice progress bars and emojis behind `if isatty(2)`? I thought so anyway, but I'll admit I've never actually looked at what npm, uv, etc. do.
matheusmoreira 57 minutes ago [-]
That's the right approach. Output goes to standard output, and user facing messages go to standard error. That way output can still be piped or redirected while the program talks to the user, and messages can also be suppressed by redirecting to the null device.
I've always been annoyed by the fact file descriptor 2 is called the "error" stream. Should have been called the "user" stream.
yjftsjthsd-h 15 hours ago [-]
> It would be nice to have an agreed-upon protocol for progress reporting. For instance, imagine of we had file descriptor 3 as "stdprogress". Programs could dump specially formatted messages there which the parent job control shell could intercept and turn into a progress display (with multiple rows for pipeline elements and such).
Different thing, but I am reminded of the BSDs having SIGINFO.
> It's not bad; but fluff like this can't be in band with the output, or at least not by default.
FWIW, I would describe stderr as being out of band. IIRC that's how e.g. pv works; `<file.img pv | dd of=/dev/foo` sends data along stdout while giving status info to the user since stderr isn't being piped.
XYen0n 9 hours ago [-]
Although not a standard protocol, `OSC 9;4` can be used to display a progress bar in the terminal emulator.
IgorPartola 13 hours ago [-]
Lots of programs report progress when you send SIGUSR1 or SIGUSR2.
mr_mitm 5 hours ago [-]
Maybe the PowerShell folks were onto something when they implemented seven different output streams [1]. But then again most users are utterly confused by this and just dump everything to the information stream when they should be using the output stream, making their code near impossible to reuse in an idiomatic way.
> It would be nice to have an agreed-upon protocol for progress reporting.
That was initially USR1 and USR2 as process signals, well, at least across binutils and coreutils.
I just wish that UNIX architecture or POSIX would have been modernized since then, like with JSONL based process communication or similar things.
In Go I usually end up building my own JSONL protocol to marshal/unmarshal states between long running processes. Wish that could've been a POSIX standard.
esalman 11 hours ago [-]
I have used click/typer packages to build some python-based CLI programs. It's easy and user-friendly way to build, but the amount of time it takes for python to start the environment followed by the actual program to do anything is annoying.
benrutter 5 hours ago [-]
Tangent, but anyone who's a fan of Typer, I'd massively recommend Cyclopts! It's essentially the same design, but takes advantage of some of the type features python introduced post Typer being written, to make things a little more consise.
Is terminal a world of “pure information’ or “a mess”? Both, it seems. Don’t dump “pages and pages of debug” text? Check. But do use boldface fonts “in a terminal independent way” and “try” to provide man pages. But because “some people” don’t know about them and “some platforms” don’t support them, provide help text by default.
Those “some” by the way are one: Windows. Do please enlighten us on the terminal-independent font control system that includes CMD.EXE.
How much is too much? Their showcase examples are more than 25 lines, more than the default size of a terminal window. The authors don’t give much weight to context, to the ability to look back on over the history of the interactive session. No, much better to splat the screen with 50 lines the user didn’t request, because helpful.
Oh, and don’t write a filter like cat(1). How the system is supposed to distinguish between reading from standard input and reading from standard input by mistake, they don’t say. Just quit and print a help message.
I have different advice: please don’t help. Please be quiet. Don’t suggest, don’t guess, dont offer, don’t assume. Just do. Do what the user said. If he wants something else, he’ll say so in time.
If you want —help to do something useful because you think your user is too dense to find the manual (condescension much?) then invoke it for him. Just maybe put a hint somewhere to press “q” to quit.
Virtually all the “help” I get on the command line is unasked-for and unwanted and unhelpful. If I fat-finger “ls”, I don’t need a suggestion to install lsof. The very last thing I want is 50 lines of noise obscuring what I was looking at before you so helpfully interrupted.
If I wanted to use a pager I'd pipe the output to a pager, no pipe to pager means I want it all dumped to STDOUT. So annoying.
I don't think I was ever bothered by the automatic paging through "less".
[1]: https://man7.org/linux/man-pages/man3/isatty.3.html
The funny thing is. I kept missing this detail every time I read through git. Feels like I was blind to the whole concept of it
I want the output visible on screen after I exit the pager. If I didn't want it on screen, I'd pipe it to a file and open that in a text editor. That will disappear when I close the file. As a bonus: I can then use grep without having to repeat whatever command I used.
Even more importantly: I want the command to behave identically regardless of whether its stdin or stdout is /dev/null or a terminal or a socket or a serial port or a pipe or anything else that it can read or write with. Try writing a script when the tools themselves change how they behave whether they're running in a script or in a terminal or elsewhere. It kinda sucks.
_less_ has a nice "&" command that is like "/" (search) but that filters instead like grep.
You can also pipe to an external command from less
But we smart coders. We think everything. Remind me later.
For example, many pagers don't work well when stdin is line-buffered (they assume they'll see individual key presses as they happen)
Pagers can also conflict with keys that the terminal emulator is using for a different purpose. This is especially annoying when the terminal emulator is using those keys for pager-like functionality in the first place!
An example of both of these is Emacs `shell-mode`.
(I personally set `PAGER=cat` in my Bash profile, which avoids most of these shenanigans)
good advice
- (2024): https://news.ycombinator.com/item?id=39273932
- (2020): https://news.ycombinator.com/item?id=25304257
> - A description of what your program does.
> - One or two example invocations.
> - Descriptions of flags, unless there are lots of them.
> - An instruction to pass the --help flag for more information.
I disagree with this. The first 3 points should all unconditionally be in the man page of the program. In my ideal scenario, the jq short help message would omit everything after the "Usage" section except for the message to run the command with --help.
This is yet another area where GUI programs on Windows 98[1] were better than today's Linux state of the art: pressing F1 opening a separate window with HTML-based help with contents, colours, fonts, text styles, hyperlinks, tables, pictures, an index, a search, is so vastly superior that it's unbelievable[2] that here we are in 2026 and Linux world is still infighting over whether a pager is a sign of weakness and low status, or whether showing help by default is a sign of a low quality programmer, for a problem that was completely solved during the Clinton Administration! (And presumably solved in a similar way earlier by classic MacOS, earlier by Amiga OS, and earlier at Xerox PARC).
Having a single output stream and trying to do everything on it is just bad design. Having the program guess what you want, or a toggle to change between working and being informative, or an environment variable to trigger the toggle, are downstream problems that can never please everybody, to avoid facing the bad design and dealing with it.
[1] https://en.wikipedia.org/wiki/Microsoft_Compiled_HTML_Help
[2] it's completely believable
Nope. For debugging the program, it is nice to have some debug tracing option, but if it's not the program's specification to produce output, it should not produce any. If the program's specification is that it produces a certain output after a certain calculation, then it shall not produce any other output, even if that calculation takes three weeks.
"cp -r from to" is supposed to be quiet until it's done or hits an error.
It would be nice to have an agreed-upon protocol for progress reporting. For instance, imagine of we had file descriptor 3 as "stdprogress". Programs could dump specially formatted messages there which the parent job control shell could intercept and turn into a progress display (with multiple rows for pipeline elements and such). It's not bad; but fluff like this can't be in band with the output, or at least not by default.
I've always been annoyed by the fact file descriptor 2 is called the "error" stream. Should have been called the "user" stream.
Different thing, but I am reminded of the BSDs having SIGINFO.
> It's not bad; but fluff like this can't be in band with the output, or at least not by default.
FWIW, I would describe stderr as being out of band. IIRC that's how e.g. pv works; `<file.img pv | dd of=/dev/foo` sends data along stdout while giving status info to the user since stderr isn't being piped.
[1] https://learn.microsoft.com/en-us/powershell/module/microsof...
That was initially USR1 and USR2 as process signals, well, at least across binutils and coreutils.
I just wish that UNIX architecture or POSIX would have been modernized since then, like with JSONL based process communication or similar things.
In Go I usually end up building my own JSONL protocol to marshal/unmarshal states between long running processes. Wish that could've been a POSIX standard.
https://cyclopts.readthedocs.io/en/stable/
I mean before asking AI to implement :)