Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

There is also 'lsd' but I still prefer eza.

For everyone interested there is a lot of modern command line tools I nowadays prefer over the old stuff:

  bat - cat with highlight
  difftastic - better diff
  gdu - ncdu for ssds (disk space analyser)
  zoxide - modern cd
  fd - find alternative
  rg - ripgrep (grep)
  fzf - fuzzy finder
  jless - json viewer with mouse folding
  dra - download and install release assets
  lazygit - git TUI
  lazydocker - docker TUI
  yazi - file manager with image preview
  zellij - better tmux / screen
  starship - cross shell prompt config
Have fun


4 additional tools I use regularly:

- task, a Makefile alternative

- hyperfine, a benchmark tool

- vegeta, a load testing tool

- sd, a better, more intuitive sed

There’s also the JSON trinity:

- jq, the well know JSON processor

- jc, convert the output of many CLI tools to JSON

- gron, make JSON greppable


Task is _amazing_

I tried magefiles[0] for a while, but Task just works so much better and isn't Go-specific as heavily.

[0] https://github.com/magefile/mage


Justfile is my favorite. Anything that requires complexity I just use Zig build. I hate make with a passion. I could see why people stick with it after learning it for decades, but for the rest of us it is a nightmare.


I looked, just now, at all the Make alternatives mentioned: Task, Mage and Just.

Those first two are nowhere near as easy to read as Makefiles. The last one, Just, looks good, though.

At least Cmake files are easy to read, but many of these alternatives are just poor UI, compared to Makefiles. I mean, using YAML of all things and thinking it's some sort of improvement over Make syntax?

1. Mage is just insane. In what world is this:

    func Build() error {
        if err := sh.Run("go", "mod", "download"); err != nil {
            return err
        }
        return sh.Run("go", "install", "./...")
    }
More readable than this:

    build:
        go mod download
        go install ./...

2. Task - not just significant whitespace, but significant whitespace everywhere, due to a poor format (YAML). Look at the example given:

   version: '3'

   tasks:
     build:
       deps: [assets]
       cmds:
         - go build -v -i main.go

     assets:
       cmds:
         - esbuild --bundle --minify css/index.css > public/bundle.css

Compare with Makefile that does exactly the same thing:

    build: assets
        go build -v -i main.go

    assets:
        esbuild --bundle --minify css/index.css > public/bundle.css
These alternatives to "Make an easier Make" appear to not know about Make in the first place.


> due to a poor format (YAML).

That's just your opinion. I'll take YAML whitespaces over Makefile whitespaces any day.

> Compare with Makefile that does exactly the same thing

Good example in favor of Task, I prefer the explicitness :) Especially when the file starts to get big. You forgot the .PHONY by the way, I hope for you there's no build/ or assets/ folder where your Makefile is.

For a more useful comparison, with actual source dependencies and build target:

Makefile:

    GO_FILES = $(shell find . -type f -name '*.go')

    ./myapp: $(GO_FILES)
        go build -trimpath -o $@

    .PHONY: build
    build: ./myapp
Taskfile:

    tasks:
      build:
        cmds:
          - go build -trimpath -o ./myapp
        sources:
          - '**/*.go'
        generates:
          - ./myapp
Makefiles are incredibly terse, but that's not an advantage. I read my code more than I write it, so I favor explicitness .


> For a more useful comparison, with actual source dependencies and build target:

Makefile:

     GO_FILES = $(shell find . -type f -name '*.go')

     ./myapp: $(GO_FILES)
         go build -trimpath -o $@

     .PHONY: build
     build: ./myapp

 Taskfile:

     tasks:
       build:
         cmds:
           - go build -trimpath -o ./myapp
         sources:
           - '\*/*.go'
         generates:
           - ./myapp

Even in this example, what is PHONY needed for?

    GO_FILES = $(shell find . -type f -name '*.go')

    ./myapp: $(GO_FILES)
        go build -trimpath -o $@

Honestly, it's still simpler to read.

> Makefiles are incredibly terse, but that's not an advantage.

Brevity is not why I prefer Makefile syntax over YAML, readability is. The minute you start trying to do anything large in a YAML definition you're going to need special editor help to keep track of indentation, and even with that, a large tree is still going to be lost off-screen because the context of any node in the tree depends on seeing the lines immediately above.

With Makefiles, any node in the tree has immediate context on the same line (the dependencies) which makes it very readable to me. I really prefer:

    target: dep1 dep2 dep3 dep4
compared to:

    tasks:
      dep3:
        cmds:
          - ...
        sources:
          - ...
        generates:
          - ...
      dep2:
        cmds:
          - ...
        sources:
          - ...
        generates:
          - ...
      dep1:
        cmds:
          - ...
        sources:
          - ...
        generates:
          - ...
      target:
        cmds:
          - ...
        sources:
          - ...
        generates:
          - ...


One day I decided to design a Makefile alternative, but I wanted to use YAML to benefit from the standard syntax and JSON schemas. I quickly realized I was just reimplementing Taskfile with different key names.

I love Task because it completely fits my mental model, I can use all the Makefile features I like without relying on arcane syntax.


Those are all very nice! I've come to be a huge fan of just as a Makefile replacement for the common case where I'm not actually computing vast build dependencies.


hyperfine is absolutely brilliant. My go-to replacement for time.


Cool. Some new ones there. I usually use a script with dra to download my release assets to `$HOME/bin`

I also use `oha` (Load Testing), `btop` (better top), `rmlint` (find duplicates) and `cheat` (similar to tldr - short manpages).

There is a blog post / video that shows how to integrate fzf with git, bat etc... it's one of the best videos I've ever seen on terminal productivity:

https://www.youtube.com/watch?v=mmqDYw9C30I

This guy is bonkers - take a look at his other videos, too


  >   fd - find alternative
  >   rg - ripgrep (grep)
NOTE OF WARNING:

BY DEFAULT these ignores anything included in your `.gitignore` folder. So if you think it is a straight find replacement, you'll likely be surprised. fd discussion here[0]

Just make sure that when recommending people these tools that this is clear because if they don't read the docs (lol who does) they'll miss this part.

This is a pet peeve of mine. I wish the people that make these replacement coreutils (and others) would leave the defaults as very similar to the original tool. I do really like the new functionalities but if you market it as "an alternative" ("It is a simple, fast and user-friendly alternative to find") then they should respect the defaults of the original because it reduces new user surprise. I mean aliases exist... So it is better to have in your ~/.${SHELL##*/}rc file to have `alias fd='fd --ignore'` than `alias fd='fd --no-ignore'`.

Side note/pro tip: use `\command` if you want to use an unaliased version. An example of this is that I have `alias grep='grep --color=always --no-messages --binary-files=without-match` but this can sometimes be problematic because the color option can change the character representation so if you pipe this into `curl` you will get errors. This is not the case in all piping, but it is a shocking and confusing experience when you first encounter it. You can validate this by `echo "Hello world" | \grep --color=always "Hello" | hexdump` and then `!!:s^always^never`

[0] https://github.com/sharkdp/fd/issues/612


> I wish the people that make these replacement coreutils (and others) would leave the defaults as very similar to the original tool. I do really like the new functionalities but if you market it as "an alternative" ("It is a simple, fast and user-friendly alternative to find") then they should respect the defaults of the original because it reduces new user surprise. I mean aliases exist... So it is better to have in your ~/.${SHELL##*/}rc file to have `alias fd='fd --ignore'` than `alias fd='fd --no-ignore'`.

I never marketed ripgrep explicitly as an "alternative." But it would be entirely appropriate to do so. An "alternative" does not mean "has exactly the same behavior." You're confusing that with, "drop-in replacement that is bug-for-bug compatible."

If people such as myself working on these new tools had your mindset, then there would literally never be any room for improving the default behavior. Which just seems like a wild position to stake out to me. Defaults really matter, and other than performance, ripgrep's default ignore behavior is far and away the thing people consistently remark as their favorite feature.


This link also has a large list of additional tools I hadn't heard of but look interesting.

https://github.com/ibraheemdev/modern-unix



Gotta love Rust (in which most if not all of these tools are written).


I didn't find zellij to be better than screen. The tabs/screens are not numbered correctly so switching directly to them requires manually counting. A non-starter for me.


If you don't like the default tab bar, you can use the zjstatus plugin (https://github.com/dj95/zjstatus) to replace it with a customizable one that can show the tab index.


From memory the index is different to the position, so if you rearrange our delete tabs the numbers become meaningless. I submitted a PR but the developers wanted it to be a separate plugin for just this. I decided it wasn't for me.


As someone who defaults to lsd, is there any reason why you prefer eza to it?


I use du-dust over gdu, but otherwise my list is almost identical to yours.


Thanks. I will definitely try that out.


Great list! I would also add:

   viddy, a replacement for watch that includes history




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: