Stop Bloating Your Shell

published on

Probably my favourite part of using Linux is that I can customise my experience.

The customisation options for some of the fundamental tools I use are endless and they are customisable by design. I have probably spent more time customising, modifying and tweaking my shell configurations than any other piece of software on my system.

For this article I will be using zsh as the example shell unless stated otherwise.

A shell is a tool, not a toy

Simply put the shell is a tool. Whether you are using it interactively or you are scripting tasks, you must use your shell correctly.

Since the shell is a tool you should be more concerned with what it is for than how it looks. You should also be aware of the dangers of using it incorrectly and the dangers of misunderstanding it while using it.

Most shells support a form of regex which allows you to be as explicit or implicit as you need when creating a command to be run. The use of the * on its own in shell scripts should be avoided for this reason. You don’t want to accidentally delete your entire home folder.

You Don’t Need Plugin Managers

The use of plugin managers for a shell is peak soydev and a completely ridiculous concept, so why do so many people fall for it? The answer is simple, they are soydevs and do not understand the shell.

The most popular plugin manager seems to be oh-my-zsh for the zsh shell. It is nothing more than an obfuscated fronted for features that are built into zsh. You do not need it to install anything. You can source these plugins manually in your .zshrc file.

Using these managers makes your shell take longer to load, adds unneeded complexity and causes problems if you want to do something outside of its scope. Not only that but it turns your .zshrc file into a complete and utter mess for no reason.

Stop using them, you don’t need them. It’s lazy and encourages bad practices.

Make your own plugins!

Do you have a ridiculous number of aliases? Would you prefer not to scroll through them? You can make these into their own plugin!

As I mentioned above with how to load a plugin you simply need to source the plugin file. Plugin files for zsh are actually just .zsh files and you can make your own. All you need to do is place your aliases in a new file, place the file somewhere appropriate, ensure that the file’s shebang is correct: #!/bin/zsh and then source that file in the .zshrc file like so: source /path/to/new/alias/plugin.zsh 2>/dev/null

I personally don’t do this with my aliases and would recommend not doing so but this is a good example of how plugins work, they are just .zsh scripts!

Aliasing correctly.

Aliases are probably my favourite part of using the shell for most of my needs. You can ensure that a command such as ls always uses colours, you can create adjacently named commands such as ll for example to run ls -l when needed.

Additionally you can bind scripts and long and complicated single line commands to a single word for ease of use. For example I use dotfiles for managing my dotfiles git repository, I have some scripts that I also like to invoke for things such as checking for updates from all programs on my system, checking crypto prices, etc that I can do with a single word instead of writing the full file path. Although I do I keep these scripts in my PATH I use a naming convention that makes it easier to tell what script it is but it is easier to just invoke them with an alias instead.

One thing you should not do with aliases however is use them to replace a program. It is bad practice to “rename” a core program such as ls with an alternative you found online. You should instead be using this tool by its name so that you are aware of what you are doing. Using aliases to obfuscate what you are doing is dangerous.


The shebang (shell bang) is used to ensure that the correct shell language is used when a file is run. For example #!/bin/sh would be used if a script is POSIX compliant only and uses no Non-POSIX commands. For example if you write a script in BASH and it uses bashisms, then your shebang should be #!/bin/bash instead.

Setting the shebang in your scripts correctly means that when you invoke them from another shell the correct shell program is used to interpret the script. There are tools for testing your shell scripts so that you know what shebang to use, what adjustments to make to use, etc. I personally quite like shellcheck but there are other options out there. However you should not rely on these tools and should be familiar with the commands you are using and how they work before committing them to a script. You can always check their man pages or other documentation before you commit to their use.

Ideally all scripts should be POSIX compliant only, bashisms are very tempting to use as they do give you more options for your script but there is a good chance you just do not need them.

Remote Shells

If you connect to other devices using a tool like ssh then you should ensure that the remote user’s shell config is configured correctly for this. A few examples of what not to do are:

Additional recommendations

When declaring your PATH variable you should do so explicitly, it may seem fun to use a script to do this but that is additional startup logic that you do not need and a script that you now need to maintain. Additionally you should not be declaring the PATH in your .zshrc file it should be declared in your .zprofile file so that your application launcher (assuming dmenu) is PATH aware.

So instead of using a script that iterates through all the sub-directories of your .local/bin/ directory just declare them like so:

export PATH="$PATH:$HOME/.local/bin/"
export PATH="$PATH:$HOME/.local/bin/go"
export PATH="$PATH:$HOME/.local/bin/sh"

This example is from my .zshrc file, which you can find here: GitLab

Learning process

Ultimately, using the shell is a learning process. The more you use it and tinker with it they more you will learn. Feel free to email me about this subject if you would like help or would like to correct anything I have said.