Five Must-Have Command Line Tools for Developers
Tags: linux, macos, terminal, cli
Published: 2024-05-21 00:53:46

---
title: Five Must-Have Command Line Tools for Developers
published: true
date: 2024-05-21 00:49:48 UTC
tags: linux,macOS,terminal,cli
canonical_url: https://www.daveyshafik.com/archives/70845-five-command-line-tools-for-developers.html
---

There are many tools that I use to improve my terminal experience, these are the top five that I use every single day to make developing code easier, quicker, and more enjoyable.

## ack

Starting with the most well known first, `ack` is like `grep` but optimized for programmers, it is both faster and simpler than `grep`, and has better results.

`ack` has several quality of life improvements by default: recursive by default (but ignores VCS folders like .git), better output display including highlighting, and it uses [PCRE](https://en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions) for pattern matching.

Just compare the _default_ output for `grep -R` and `ack` (respectively):

[![](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-3.36.33%E2%80%AFPM-1024x388.png)](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-3.36.33%E2%80%AFPM.png)
_Search for “Interface” in the “src” directory using grep: grep -R Interface src_

[![](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-3.36.55%E2%80%AFPM-1024x969.png)](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-3.36.55%E2%80%AFPM.png)
_The same search using ack: ack Interface src_

Sure, the output for `ack` takes up far more space, but it groups matches by filename (highlighted), adds line numbers, and highlights the matching text.

Additionally, you can easily include specific file types using the `-t` or `--type=` flags, e.g. to only search PHP file types which includes `.php .phpt .php3 .php4 .php5 .phtml` **and** files with a PHP shebang (e.g. `#!/usr/bin/env php`) on the first line you can use `-t php` or `--type=php`. You can also use the type name itself as a flag instead e.g. `--php`.

You can easily expand these types by adding a `.ackrc` file to your HOME directory and with a few lines either add additional file matches, or add a new file type entirely. For example, you can use `--type-add` to add `composer.json` (specifically) as a filename to search when searching through `php` file:

```
--type-add=php:is:composer.json
```

You can create a new file type for `.env` files called `env`:

```
--type-set=env:ext:env
--type-add=env:match:/^.env.*$/
```

Or to create a new file type for blade templates:

```
--type-set=blade:match:/.blade.php$/
```

With these in place a search for `ack --php dshafik/bag` will return results from `composer.json`, while a search for `ack --blade someVariables` will only match results in `*.blade.php` files, and `ack --env APP` will match all lines containing `APP` in your `.env*` files.

## delta

`delta` describes itself as “a syntax-highlighting pager for git, diff, grep, and blame output”, but I find that to be somewhat ambiguous: it is a syntax-highlighting pager for `git diff`, `git grep`, and `git blame` output. It will actually be used by all git operations that output diffs, not just `git diff`.

Integration with `git` is easy, just add the following to the `.gitconfig` file in your HOME directory:

```ini
[core]
pager = delta

[interactive]
diffFilter = delta --color-only

[delta]
navigate = true # use n and N to move between diff sections

# delta detects terminal colors automatically; set one of these to disable auto-detection
# dark = true
# light = true

[merge]
conflictstyle = diff3

[diff]
colorMoved = default
```

Personally, I also like to add `line-numbers = true` to the `[delta]` configuration to enable line numbers.

Once you’ve completed this, `git `will start to output much easier to read diffs:

[![](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-4.35.42%E2%80%AFPM-1024x550.png)](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-4.35.42%E2%80%AFPM.png)
_delta output with git diff_

As you can see here, it calls out the filename at the top, and is smart enough to show the relevant code structure that contains the change and the line on which the diff context starts, in this case the namespace, starting from line 7, but it could also be a class or a function or method. It also features per-character diff highlighting, on top of the standard line highlighting — in this case you can see that I added a new value to the Attribute options bit mask.

## httpie

The next tool has been in my toolkit for a long time, _httpie_, a python tool for making HTTP requests. It is usually referred to as “curl for humans”. Once installed, _httpie_ is available as the `http` command, which then folllows a syntax similar to the HTTP protocol itself:

```
http <METHOD> <URL> <HEADER>:<HEADER VALUE> <HEADER2>:<HEADER2-VALUE>
```

for example, this will display the response from [bagvalueobjects.com](https://bagvalueobjects.com):

```
http GET https://bagvalueobjects.com
```

By default, it will show the response headers and the response body, but this is easy to change using the `-p` flag. The following will show _only_ the request and response headers:

```
http -pHh GET https://bagvalueobjects.com
```

The value for `-p` are `H` (request headers), `h` (response headers), `B` (request body), `b` (response body).

Request headers and body? Well, yes, you can send POST requests just as easily:

```
http -pHhBb POST http://httpbin.org/post foo=bar
```

You can see that we have a new argument at the end `foo=bar`, this will send a JSON body with the value `{"foo":"bar"}`. You can add as many properties as you like to the end of the command. You can also pass the `-f` or `--form` argument and it will send the key-value pairs as `multipart/form-data` instead.

If you need to send complex JSON, use `:=` instead, like so:

```
http -pHhBb POST http://httpbin.org/post foo:='["bar", "baz", "bat"]'
```

This will send the body `{"foo":["bar", "baz", "bat"]}`.

There are tons of other options including being able to use files as the post body, send files, support for sessions, authentication and more.

## gron

Many folks are familiar with `jq`, a great command line utility for working with JSON, if you’re not familiar with it, I highly recommend that you check it out.

Sometimes however, `jq` is just too complicated, or the result isn’t exactly usable. Sometimes, you just want to be able `ack` (née `grep`) some JSON for a specific value. `gron` will break down JSON into valid Javascript assignments, for example, the simple body from our _httpie_ example above might looks like this:

```javascript
json = {};
json.foo = [];
json.foo[0] = "bar";
json.foo[1] = "baz";
json.foo[2] = "bat";
```

As you can see, this creates a variable `json`, and assigns an empty object to it, it them sets the `foo` key to an empty array, and then sets each of the numeric keys to it’s specific value.

Because it’s broken down to one assignment per line, you can now easily and reliable pipe it through ack or grep and find whatever you need.

A more practical example: list all the require-dev requirements in a composer.json files:

```
gron composer.json | ack require-dev
```

This will output the following:

```javascript
json["require-dev"] = {};
json["require-dev"]["captainhook/captainhook-phar"] = "^5.23";
json["require-dev"]["captainhook/hook-installer"] = "^1.0";
json["require-dev"]["fakerphp/faker"] = "^1.23";
json["require-dev"]["infection/infection"] = "^0.28.1";
json["require-dev"]["larastan/larastan"] = "^2.0";
json["require-dev"]["laravel/pint"] = "^1.15";
json["require-dev"]["orchestra/testbench"] = "^8.0|^9.0";
json["require-dev"]["phpunit/phpunit"] = "^10.5|^11";
json["require-dev"]["ramsey/conventional-commits"] = "dev-allow-sf-7";
json["require-dev"]["roave/security-advisories"] = "dev-latest";
json["require-dev"]["symfony/var-dumper"] = "*";
```

We can then turn this back into JSON, and feed it into `jq` to get the values using `gron -u` or `gron --ungron`:

```
gron composer.json | ack require-dev | gron -u | jq '."require-dev" | keys[]'
```

This will output:

```
"captainhook/captainhook-phar"
"captainhook/hook-installer"
"fakerphp/faker"
"infection/infection"
"larastan/larastan"
"laravel/pint"
"orchestra/testbench"
"phpunit/phpunit"
"ramsey/conventional-commits"
"roave/security-advisories"
"symfony/var-dumper"
```

Alternatively, let’s use `gron` to _remove_ any custom scripts from our composer.json. We can use this by again, piping the output through `ack`, but this time using the `-v` argument to exclude matches, and then passing it back to `gron -u`:

```
gron composer.json | ack -v json.scripts | gron -u
```

The resulting JSON will be identical to the original, but with the entire `scripts` key missing.

## bat

The last tool I want to cover is a new addition to my local environment, and that is `bat`, a replacement for `cat` with syntax highlighting.

`bat` has a few advantages over `cat` besides syntax highlighting by default: the output is paged, includes the file name, and line numbers:

[![](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-5.28.54%E2%80%AFPM-1024x550.png)](https://www.daveyshafik.com/wp-content/uploads/2024/05/Screenshot-2024-05-20-at-5.28.54%E2%80%AFPM.png)
_syntax highlighted code using bat_

While `bat` doesn’t provide as much utility as most of the other tools on this list, it’s simplicity makes it perfect as a drop-in replacement for `cat`, allowing you to just add `alias cat=bat` to your terminal configuration and forget about it.

## Next Steps

If you want to try any of these tools for yourself, they are all available using `brew`, which is available on all platforms.

This list was aimed specifically at improving your development workflows, however, I have also made many changes to my terminal environment as a whole which also aids me in getting my work done faster, and easier. If you want to hear more, let me know in the comments below!