74
votes
Share your personal dotfile treats and Unix tool recommendations
I am currently preparing for a new job and cleaning up my dotfile repository. During the process, I had the idea that it would be nice to create a list of amazing tools, aliases, functions, and recommendations together.
I will start.
First, here is a list of nice tools to apt-get install
or brew install
that I can wholeheartedly recommend:
nvim
is just an amazing text editor.fzf
is a very good fuzzy finder util. For example, you can quickly find files with it.eza
is a goodls
replacement (and the successor ofexa
).bat
is a great replacement forcat
with nice integrations and many options.stow
is great for managing your dotfiles. Thanks to @TangibleLight for telling me about it some while ago. I really love it.tmux
is a terminal multiplexer, i.e. you can have many sessions in one single terminal window. It's easy to use and super helpful. (When on a mac, I prefer iTerm tabs, though.)nvm
is practically a must if you are working with Node.glow
is an excellent markdown reader.tldr
is a niceman
replacement. (You must runtldr -u
after installing it to update available texts.)z
, an amazing tool for switching directories quickly.
Also, I can recommend Oh My ZSH! which I have been using for years.
Here is a small list of aliases I enjoy (I have 100+ aliases and I tried to pick some others may enjoy as well):
# Serve current dir
alias serve="npx serve ."
# What's my IP?
alias ip="curl --silent --compressed --max-time 5 --url 'https://ipinfo.io/ip' && echo ''"
# This should be the default
alias mkdir="mkdir -p"
# Nice git helpers
alias amend="git add . && git commit --amend --no-edit"
alias nuke="git clean -df && git reset --hard"
# Make which more powerful
which='(alias; declare -f) | /usr/bin/which --tty-only --read-alias --read-functions --show-tilde --show-dot'
# This saves so many keystrokes, honestly
alias -- +x="chmod +x"
# Turns your path into a nice list and prints it
alias path='echo -e ${PATH//:/\\n}'
# Map over arguments and run a command
# Usage: map <command>
# Example: ls | map cat
alias map="xargs -n1"
And, finally, here are some fun functions:
# Get cheat sheets for almost anything!
# https://github.com/chubin/cheat.sh
cheat() {
WITH_PLUS=$(echo $@ | sed 's/ /+/g')
CAT_TOOL=$(command -v batcat || command -v bat || command -v cat)
curl "cheat.sh/$WITH_PLUS" | $CAT_TOOL
}
# Send everything to /dev/null
nullify() {
"$@" >/dev/null 2>&1
}
# Create a new dir and enter it
mk() {
mkdir -p "$@" && cd "$_"
}
# Create a data URL from a file
# Source: https://github.com/mathiasbynens/dotfiles/blob/master/.functions
data-url() {
local mimeType=$(file -b --mime-type "$1");
if [[ $mimeType == text/* ]]; then
mimeType="${mimeType};charset=utf-8";
fi
echo "data:${mimeType};base64,$(openssl base64 -in "$1" | tr -d '\n')";
}
I may add more to this later:
bash
andzsh
with colors, git integration, auto-complete, better scripting, and more.bash
works withfish
(especially because most scripts start with#! /usr/bin/env bash
). But in particular,nvm
doesn't, you neednvm.fish
.rg
(ripgrep):grep
(search text in files) but better.fd
:find
(search files by name and type) but better.ninja
:make
(build C/C++) but faster. You use it to build CMake projects by passing-GNinja
to the command that generates the CMakeFile.mold
:ld
(link C/C++/Rust/nim object files) but faster. Similarly, you can configure CMake projects to use mold viaDCMAKE_EXE_LINKER_FLAGS="-fuse-ld=mold" -DCMAKE_SHARED_LINKER_FLAGS="-fuse-ld=mold"
. It also works with Rust and Nim according to the README.rename
for macOS (viabrew install rename
): batch rename files.restic
: command-line backup tool.ncdu
: command-line disk cleaner (find and remove large files).nnn: a very fast and lightweight TUI file manager with vim like key bindings. I use it less for file management and more as a faster way to cd around the file system.
yazi: another TUI file manager, a bit slower than nnn because it does more (previews). I tend to use yazi for actual file management.
nnn is so critical to my workflow. Even just going up one directory is fewer keystrokes with nnn.
cd ..<Enter>
(6 strokes) vsn<Enter>hq
(4 strokes). The strokes saved increase with more cd complexity (eg, going up and over a directory).Being a nnn user for some years I was intrigued by yazi and tried for a few days. It is indeed very good, but I still prefer nnn.
I need to do many more keystrokes to achieve the same things in yazi. Nnn is way better at this.
Also I am very diligent with my filenames and organization so I don't see a need for file preview and icons. I find these nerd font icons quite ugly.
Great project anyway.
cb
I can't recommend
cb
enough!https://github.com/niedzielski/cb
It's a pretty simple concept: run different things depending on whether stdin is connected to a terminal which allows you to write a pipeline like this:
This sorts the contents of your clipboard and then puts it back to your clipboard. It totally bust my brain when I first saw it.
I wrote a similar thing but for images. I don't use it very often but it is handy for checking clipboard screenshots before pasting them into a website.
moreutils
is also interesting to checkout. One of the commands in that package issponge
which let's you do a similar thing to the above and buffer output for files.htop
I've been using
htop
for about ten years but I never took the time to configure it until last weekend! The defaults are pretty good but htop can do a lot more than showing you which process is hogging all your RAM!!t
will display a process trees
will runstrace
on the highlighted processl
(lowercase L) will show all open files for the highlighted process (usinglsof
)/proc/$pid/io
but sometimes it is useful to see it across all processesfreerdp
Recently I was having trouble with nomachine on HiDPI displays and I discovered
freerdp
which I hadn't prior heard of before. The screen is much clearer now:On server:
On client:
Quickemu
handy for spinning up Windows when you need it:
systemd
Some people like https://github.com/Nukesor/pueue but I like systemd. For temporary commands I want to run (download jobs, etc) I put them in text files and they run...
This is a work-in-progress but I'm enjoying it a lot so far:
progress
You can use
progress
to track a bunch of ffmpeg jobsAnd of course I put my whole home folder in git:
NixOS has been the biggest boon to my enjoyment of computing in a long, long time.
The biggest feature for me is consolidating the endless methods and formats of config files into both a centralized location and - most importantly - a standardized language with standardized logic.
My favorite example is vim configuration. The various methods of configuring neovim (old vimscript options, the new lua config, plugin managers, plugin installation, and various plugin-specific configs) have all been consolidated. This makes maintaining and adding to the configuration an absolute breeze. A small edited excerpt:
Full neovim config
Consolidation of how to configure things extends to pretty much every other part of the system you can think of. Once you understand the syntax of the language and where to find the options (search.nixos.org), system configuration becomes extremely easy to maintain. It has been much less painful than the old-school way of needing to learn all the different ways base Linux wants to be configured, let alone 3rd-party programs.
Indeed, most of the common options of both the Linux OS and 3rd-party programs have been pre-packaged into simple
true/false
flags by the community or otherwise are much more consistent to configure. Failing that, nearly every program includes an option to get back down into the config files themselves, for non-standard needs.Some choice examples:
Generic auto-login =
services.displayManager.autoLogin.enable = true;
Install, enable, and run a service =
programs.jellyfin.enable = true;
Change user shell:
Extremely standard boilerplate for most self-hosted services:
Slightly more in-depth configuration for the Transmission torrenting service - config is extremely typical of a service with many options
The main con is that NixOS does have a learning curve. Its not overly difficult, but NixOS needs things done in its own particular way. Pre-existing Linux knowledge will lead you astray until you learn which parts you can keep and which parts you need to forget. And, admittedly, the documentation and wider community assumes a level of understanding about Nix (the language) that makes the initial learning hurdle harder than it needs to be. However, once NixOS (and to a lesser extent Nix) clicked for me, I fell in love and have not gone back to a "regular" distro ever since.
I also intentionally stayed away from gushing over the usual Nix(OS) features I hear praised all the time (immutable systems, dev shells for per project package management, easy building of specific versions of packages) in favor of what has been my own favorite feature (and something I hear much less about) - the return of the pure joy of configuration.
I always want to try and end up overwhelmed.
If I need to learn all of that and than still maintain my home directory full of dotfiles, I don't see much of a point.
But then I heard there is home manager to solve that, and then I heard about something called flakes and by that time I was too overwhelmed with information and dropped. I'll give it a try again sometime soon.
Gradually experimenting and configuring Nix on a spare computer if you have one, or a virtual machine, is definitely a less stressful and easier way to get into Nix. That’s how I did it.
And personally, I would focus on learning regular Nix stuff and setting up home-manager before learning about flakes. In my opinion, flakes solve a very specific problem, and it’s not a problem that someone starting out with Nix or just using NixOS as a desktop Linux environment is going to run into very often. Even then, flakes aren’t the only way to solve that problem.
(And to be clear, that problem is: “I need to reproduce this software at this exact version/commit, including all of its dependencies”.)
You're right that NixOS+home-manager will replace maintaining almost all other configuration files.
And you're also absolutely right that its an information-dense overload all at once. Personally, I'd recommend starting with a small, pre-made template (I like nix-starter-configs - use the minimal version for minimal info overload) and just jumping in one day in with the intention to configure a system and install things. Ignore flakes and anything fancy for now. Its easy to come back to those later, but you can only start once!
I hope NixOS treats you well when you give a try again!
How do you configure Neovim through Nix when you need something more complicated than basic options? (Eg writing a custom lua function)
I’m not a (Neo)Vim user so I’ve never configured it with Nix, but you can almost certainly just write your custom Lua code inside your
configuration.nix
file, and it will be added to a declarativeinit.lua
.This seems to be a program/package for nix that helps make that process cleaner: https://github.com/nix-community/nixvim
As for whether that’s better/nicer than just managing your
init.lua
normally, that’s up to you.Personally, I keep my Emacs and Nix configs separate. It’s the only program I don’t configure with Nix, though, and that’s only because I have some very specific requirements for my Emacs configuration that Nix doesn’t fit into.
All of this is correct, as far as neovim goes.
And to be clear, my example in the OP of this thread was with using nixvim. Here's how you'd add lua:
which will be added to init.lua.
@fxgn Its worth noting that under the hood, nixvim is just filling out pre-made templates in vimscript (for editor settings) and lua (for plugin installation/settings, etc.)
The end-user also has the ability to tap into this and use the same framework to configure at whatever abstract level they want. See these docs for details.
Thanks for sharing your experience. Can you add proprietary drivers on Nix..? Run Steam..? Play games?
Of course! Here's a video about some common configurations for playing games on NixOS:
https://www.youtube.com/watch?v=qlfm3MEbqYA
Thanks! I always appreciate your feedback on these topics. I'm thinking about it. Right now Fedora is working for me but I've been intrigued by Nix. Thanks for the research material.
Tools
stow
-- I don't use this for dot files, but I do use it heavily for managing locally built "packages" in/usr/local/
that I've compiled from source. (This was kind of its original purpose)magick
-- Working with graphics programming for a living, I do a ton with images. At its simplest it'll just convert images between formats. But it can also do a ton of image processing and other operations on them. Think of a CLI for Photoshop filters and you start to get the idea. I often prefer Imagemagick to GUI tools because it's so easy to rerun a filter chain if the input changes. There's an insane amount of power here.difftastic
-- A nice, somewhat more syntax aware CLI diff tool.pandoc
-- It's nice to be able write markdown or org-mode files and then export to other formats. I'd much rather write something in my text editor and convert it to Jira markup than fight Atlassian's on-line editing tools, for example.emacs
-- Another amazing text editor. :-)pdfimages
-- Rip embedded image files out of a PDF file. It just extracts all the embedded data streams to numbered files, so it's effectively lossless and gets you the images at their full resolution after a bit of spelunking to figure out which is which.Aliases
alias rshare="chmod -R go=u-w"
-- Recursively copy user read and exec perms to group and other to make a subdirectory readable to others.alias runshare="chmod -R go="
-- Undo that by recursively stripping off the perms for groups and others.alias ccat="pygmentize -fterminal16m"
-- Likecat
but with a colorization filter. (I should probably trybat
sometime, but I've been using this for many years.)alias pdiff="git --no-pager diff --no-index --patience --color=auto -U15"
-- Rungit
's patience diff on two arbitrary files.Functions
Note that I use
zsh
. YMMV with these.function pdf2png() { gs -q -dQUIET -dSAFER -dBATCH -dNOPAUSE -dNOPROMPT -dMaxBitmap=500000000 -dAlignToPixels=0 -dGridFitTT=2 -sDEVICE=png16m -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -r600 -dEPSCrop -dUseCropBox -dFirstPage=1 -dLastPage=1 -sOutputFile=$2 $1 }
-- Render the first page of a PDF file to a PNG image at high-ish resolution.function para() { xargs -I{} -P$2 sh -x -c "{}" < $1 }
-- Take a file of command lines and a process count and run the commands in parallel.function countdn() { local c; for c in {$1..1}; do echo -ne " $c... \\r"; sleep 1; done }
-- Take a time in seconds and give me a countdown. Sometimes useful when I want a cooldown or to rate-limit steps in a larger script.function vbreak() { echo "\033[1;95m\n"; for r in {1..3}; do for c in {1..$COLUMNS}; do echo -n \#; done; done; date; echo "\n" }
-- Gives me a big magenta bar across my terminal, along with the current date and time. Useful when I want something of an easily visible section break in my terminal's scroll-back buffer.function semis() { tr -d -c ';' < $1 | wc -c }
-- Count semicolons in C-like source code to get a rough estimate of size. (I'll use other tools likecloc
,sloccount
, ortokei
, too, but this one is simple and easy to understand.)Here's my dotfiles repo and here's some stuff that I use:
Fish shell. This was already mentioned by @Jakobeha, but I think he didn't give it nearly enough credit. Fish is a shell done right. If you only use your shell for running external commands, it provides you a ton of built-in convenience features. If you write some scripts, it'll be even more useful, since the syntax is so much better than any POSIX compliant shell.
For example, to make a custom prompt in bash, you need to mess with
$PS1
and ANSI color codes. In fish, you just need to define a function calledfish_prompt
in your config, and inside of that function you can do whatever you want and justecho
stuff out, and that'll become your prompt. And yes, you don't need to google color codes - fish has a built-inset_color
command.zoxide. Incredibly useful. It automatically remembers every single directory you cd into, and allows you to quickly switch between them. For example, if you are often in a directory
~/Documents/Projects/foobar
, then just typingz f
will bring you to that directory.autorestic. This allows to automatically back up all of your files to basically any cloud storage, eg. S3, Google Drive or whatever else you use. Very configurable and easy to set up.
xdg-ninja. I hate when programs put their files straight in my home directory. Things like
~/.config
or~/.local/share
were made for a reason, but unfortunately not all programs use those directories by default. Runningxdg-ninja
will scan your home directory and show you all the ways you can clean it up by setting env vars or config options that force programs to use proper locations for their stuff.numbat. A super cool calculator with support for a lot of units and automatic conversion between them. So you can just type something like
200 km / 50 min -> mph
and it'll show you the result. It's actually a fully functional programming language, so you can even write scripts in it if you need to calculate something more complicated.chezmoi. GNU stow, but cooler. This is the thing I use to manage my dotfiles, and it's awesome. It automatically puts everything into the right place, supports templating for things that differ depending on the system, can extract secrets from your password managers in case some configs contain private information that you don't want to have in your public dotfiles repo, and a lot of other awesome stuff. Highly recommend.
People are also mentioning aliases their use, so I'll give one recommendation.
It's very common that I need to just quickly test something but don't want to create a directory for it and then delete it. This command makes a temporary directory that I can use to do whatever and it'll all be deleted on the next system reboot.
I also use this little helper function that allows me to use
ipython
as a python repl and regular python for running scripts:That is really interesting, thanks for the tip.
I like this one, but that would mean things hang around for a month. Forced reboot due to windows updates is usually the only time I actually shut the machine down, just hibernate otherwise.
Here's an example from my dotfiles:
https://github.com/flexagoon/dotfiles/blob/3fed42126ce7773812ed85b5efeac99e76190819/dot_config/autorestic/dot_autorestic.yml.tmpl#L24-L27
I mean, sure? You'll have some random stuff in a directory named
/tmp/tmp.h8UqJo
that will eventually be deleted. Doesn't really seem like an issue. It also seems like systemd automatically deletes untouched files in/tmp
after 10 days of inactivity, even if you haven't rebooted your system.I missed the fact that the folder is located in /tmp. I was picturing my home directory and repos littered with these temporary folders. That makes much more sense and is very cool!
I like that one, thanks for sharing.
I've also seen people do something like
Which runs a shell in a temporary Docker container that gets deleted when you exit it. Could also be useful depending on what you need.
Some of my favourites I don't think have been mentioned yet:
qalc
, a command line (and GUI) calculator that can do algebra, unit conversions, and a ton more, while still being easy enough to use for quick calculations. It should be available in your package manager aslibqualc
ive been using speedcrunch, because I like SPEED
Tools:
nmap
- If you need to connect to things, you'll find this handy, to see if the port is openwl-clipboard
- pipe your outputs to your gui clipboardAliases:
Show git history in
fzf
with searchable commit summaries on left and a diff on the right.Browse a git diff with searchable files on the left and diffs on the right:
Both are fish functions, but you can extract the git/fzf one liner to get the core of the command.
Here's some of my aliases. I really like the last one.
Lots of good tools, but I also like improving the prompt text. Here is a screenshot of the current version. I've been using this format for 20 years. Between the color and the longish line, it makes a good visual separation between the output of commands.
I like how the Starship prompt looks, but it's too slow for me due to all of the additional features that I don't need. So I made a simple prompt that looks just like Starship but in a few lines of fish:
Meta comment because I read every post like this I see but rarely end up actually learning any of the tools:
How do people handle scenarios like SSHing into a machine that you don't have configuration control over? For me, even just the lack of my
.ssh/config
file on remote machines breaks my muscle memory and annoys me.I've wanted to build out a nice
(n)vim
/tmux
configuration for a while, since the context switch between VS Code on my local machine andvim
for little edits on remote machines is a pain, but it seems like it'll be a hassle to bring my configs along with me to every machine I touch.For transporting your shell, aliases, plugins, and other customizations to a remote device, this might work: https://github.com/xxh/xxh
Emacs has TRAMP, which makes editing remote files seamless, as if they were local files.
Visual Studio Code has a similar feature documented here: https://code.visualstudio.com/docs/remote/ssh
I'm sure (Neo)Vim has something as well.
xxh
works well, but it can take some time to set up, depending on how extensively you have customized your shell. In college I briefly used it to access two systems:In both of those cases it worked pretty well, but I don't know how well it would work while trying to access a Linux server from a macOS machine, for example. It shouldn't matter. Shell is supposed to be portable and all that, but it might make a difference.
Also, because it's a cool story:
In college, our parallel programming courses required us to test and submit our projects on Frontera, which the professor would also use to grade our submissions. The class was tough. Each week, we were cutting our teeth on a new way to write parallel code in C++. It was by far the most interesting and rewarding class I took at university though.
It was also really cool watching code that would take hours to run on your local machine finish in seconds on Frontera.
They gave each student a crazy high computation budget, way more than we were ever going to use for the class projects. So, we had a lot of opportunities to experiment with writing our own parallel code, and to just generally dick around on a computer that was easily the most computationally powerful thing we ever had access to. As long as we weren't running intensive Monte Carlo simulations or plotting funny parabolas from Russia to the US, the admins really didn't care how much we burned through our computation budget.
I use syncthing to synchronize
.config
and.local
between machines that I own, and git to synchronize other folders including .ssh/config.For .ssh/config specifically, I think it is possible to use SSH Agent Forwarding. Does that not include hostnames? I haven't used it often but I would be surprised if it didn't include config like that
But for docker containers and other servers I generally just type everything in my shell and then prepend
ssh -t $server_name
at the beginning. Even when running interactive programs liketop
orsudoedit
I'll take advantage ofControlMaster
shared sockets but I don't rely too much on the remote shell... Sometimes it is a little more tedious but this way I'll always have the command history.Sorry if I am misunderstanding your problem, but for .ssh/config, you could use the ssh-agent to forward your keys and such I think? This video might do better at showing what I am thinking
As usual, the new(ish) cool “basic” necessities (fzf, ripgrep, fd, tldr etc.) have already been mentioned.
Here is my answer from the last time this topic came up, hopefully you’ll find something new and/or interesting there, haha.
I may update this comment once I get back home and have time to think of some more tools.
Edits:
icat
– cat for images – is amazing.…, and then aliases to make it even quicker/easier to remember:
mpv
is an excellent video player you can launch from the command line – and even with remote files/URLs (all that are supported byyt-dlp
should work).Tools
ls
outputs.With the combo of vcsh, home manager, and Ansible, I'm at a point where I can set up a new machine to have the same set of tools I use day to day after pulling down my dotfiles repo, creating a new config entry for the new machine, and running a few commands (and dealing with edge cases and errors).
Aliases and functions
Dealing with Git conflicts when merging or rebasing changes to a package manager's lockfile.
Almost always what I want to do is to reset the lockfile to the 'upstream' state first and then regenerate it to apply my local change. This wasn't always a smooth process as I needed to stop and think whether to use
--theirs
or--ours
for the first step, and one day I made these aliases.Remove author and commiter names and emails from Git history.
As part of my day job, I review submissions for a take-home coding challenge that's part of my team's work sample interview set. They come in Git repos, which I clone locally, and I remove author and commiter names and emails in an attempt to ward off any bias that might seep in as a result of seeing names or emails while inspecting commits.
Move to the root of the current Git repository.
Can't remember why I defined this as a function and not an alias.
(I'm amused that all of the aliases and functions that I thought worthy of sharing turned out to be Git related.)
This feels like one of those cases where ShellCheck would go “expands when defined, not when used” when trying to set it up as an alias – i.e., on shell session startup, it tries to set the directory that it would later
cd
to (so something like your home directory) just once and statically keeps it that way, ignoring working directory later.But I could also be totally wrong here, haha.
I use the silver searcher (
ag
) instead of ripgrep or ack. I made a little wrapper script which lets you search just for words, and it will find results regardless of snake_case, SCREAMING_SNAKE_CASE, CamelCase, lowerCamelCase.The key part is
| sed 's/ /[^a-z]?/g'
, which you could probably use with ripgrep, etc.Also wanted to mention jq, which I use often for pretty-printing JSON (and occasionally doing searches in them).