Command Line Snippets

The Fine Art of Snippet Curation

Wherein I ramble on a bit about a command line tool that I enjoy using to curate my collection of complex and seldom used but powerful CLI one-liners/snippets, and share some that I’ve made for certain command line tools.

This article is aimed at folks who enjoy using their Unix-like operating system command line, and for those who would also like to learn about a neat tool and system for curating and using a personal collection of command line snippets.

Most specifically, let us consider the cognitive effort associated with recalling complex or powerful, but often little used command line snippets. For example, it can be extremely handy in certain circumstances to extract the files from a Debian .deb formatted package on a BSD style system, but who can easily recall that it is done with a command like:

$ ar vx <package_name.deb>

or how about showing the number of connections in use by PID for a process with strace? That’s:

$ strace -p $(pidof <process_name>) \
  -f \
  -e trace=network \
  -s 10000

How do I add an Internet password to the macOS Keychain from the command line again? Oh, yeah:

$ security -v add-internet-password \
  -a <account> \
  -s <server> \
  -w <password>

All the handy snippets a regular user of the command line cannot fit in their head need some other place to reside. For many, this place will often be a text file of some sort&emdash; so how about the idea of using a text file of a certain format that brings useful per-snippet attributes and works with a neat CLI tool for managing and searching them?

Some people are successful with the built-in snippet capabilities of their preferred text editor. Having never really tried my editor’s own snippet system, I wanted a more universal tool where the snippets had more usefulness both in and outside of the text editor environment as well.

To that end, I’d previously used a GitHub gist to stash my snippets. Then eventually, a git repository of Markdown documents represented a carefully cataloged snippet collection, but let me tell you&emdash; it was not as easy to search and keep synchronized between systems as it is with the tool I use for this purpose now.

Say hello to pet

The tool in question is called pet by Teppei Fukuda. It is a fantastic and focused MIT-licensed, Go-based CLI tool that interfaces with a listing of CLI snippets that you keep in a TOML formatted text file.

After using pet for about one year, I’ve found it to be a minimalistic, but powerful approach to using snippets.

Once you have installed the pet binary, it can be used in handy ways, the simplest example being to just list the snippets:

$ pet list

The output is essentially the complete raw TOML of your snippet collection:

Screenshot showing pet list output

Example 'pet list' output

As your personal collection of snippets increases in number, you can use pet search to quickly find them:

$ pet search

A screenshot showing an example pet search

An example of pet search

pet can automatically interface with two popular interactive filtering and selector CLI tools, fzf and peco to make navigation and searching of your snippet collection a breeze.

A screenshot showing filtering in pet

Filtering in pet search

You can also tag snippets with # and search for tagged snippets by tag.

You can pass the search result/composed command to a clipboard wrangling tool like pbcopy on macOS:

$ pet search | pbcopy

and have the command ready to use with a ⌘+v.

For Linux, you can do the same with xclip or xsel.

$ pet search | xclip -selection clipboard

One of the nice things about the snippet format is that you can use dynamic argument placeholders for example values and pet will prompt you for the actual values, which it will then insert into the composed command line.

In practice, the UI prompting appears as shown in the following screenshot, which contains 3 arguments: a filename, a source string value, and a replacement string value.

A screenshot showing an example of dynamic arguments in pet

An example of dynamic arguments

This results in a nicely composed and ready to use command line, like this:

$ find ./ -name test-file.txt \
  -exec sed -i '' -e 's/sashimi/nigiri/g' {} \;

The tool is simple and elegant in its usage while doing what it does very well.

You can use other pet commands to add new entries, like pet new or edit the existing snippets with pet edit, which will invoke the editor you specify in the configuration file.

You can also use pet sync to synchronize your snippet collection to a GitHub gist or to GitLab so that it can be readily used in multiple environments.

$ pet sync
Upload success

Check out the pet README for full documentation and usage examples!

hashipets

As an example of a relatively comprehensive example snippet collection, I created hashipets, which is a curated collection of helpful snippets specifically for HashiCorp command line tools like Vault, Consul, Nomad, Packer, Vagrant, and Terraform.

Based on the accompanying README from the hashipets project, I’ll demonstrate here how they might be used with pet and peco. That guidance is specifically for a Mac, but I will show the process for Linux here instead.

Install pet

The quickest way to install pet for Linux is to download a binary release from the GitHub project:

Visit https://github.com/knqyf263/pet/releases and download the correct .tar.gz for your OS and distribution.

For example, we’ll be using pet_0.3.4_linux_amd64.tar.gz:

$ sudo tar -C /usr/local/bin -xzf pet_0.3.4_linux_amd64.tar.gz

$ pet version
pet version 0.3.4

Yay, now pet is installed and you just need a selector, some configuration, and snippets!

Choose a Selector / Fuzzy Finder

Now it’s time to pick a fuzzy finder for use by pet; it’s necessary for all of the convenience features, like searching. The most common of these tools and automatically supported are fzf and peco.

The hashipets project example uses peco, so this guide will as well. Feel free to try fzf as it is a great search tool as well.

Install peco

The quickest way to install peco for Linux is to download a binary release from the GitHub project:

Visit https://github.com/peco/peco/releases and download the correct .tar.gz for your OS and distribution.

In this example, it’s peco_linux_amd64.tar.gz under the 0.5.3 release tag.

$ tar  -zxf peco_linux_amd64.tar.gz
$ sudo cp peco_linux_amd64/peco /usr/local/bin/

$ peco --version
peco version v0.5.3 (built with go1.10)

You’re now ready to configure pet and peco.

Configure pet to use hashipets snippets

In this example, we will just clone the hashipets repository to a temporary directory, then configure pet to use its snippets.

$ export HASHIPETS=/tmp/hashipets
$ git clone https://github.com/brianshumate/hashipets.git $HASHIPETS
$ pet configure

Use the value from $HASHIPETS to create the full path for the snippetfile option value: /tmp/hashipets/hashipets.toml.

Here’s a complete pet configuration example:

$ cat ~/.config/pet/config.toml
[General]
  snippetfile = "/tmp/hashipets/hashipets.toml"
  editor = "vim"
  column = 40
  selectcmd = "peco --layout=bottom-up"

[Gist]
  file_name = "my-custom-snippets.toml"
  access_token = "42c0ffee8ddc568ffc0ffeeae8ac0ffeebe2a474"
  gist_id = "c0ffee3b76be396c0ffeede8dc0ffe73"
  public = false

Here’s what’s going on in the previous config.toml example:

  • General pet settings
    • snippetfile: the path to our snippets
    • editor: the editor invoked with pet edit
    • column: the target display column width
    • selectcmd: the command line for the select/search tool
  • Gist settings
    • file_name the gist filename
    • access_token: the GitHub personal access token
    • gist_id the gist ID string
    • public whether the gist is public or not

Configure peco

Go ahead and set up a custom peco configuration if you’d like as well; the one from hashipets is a good fun start:

$ mkdir -p ~/.config/peco &&
  tee ~/.config/peco/config.json <<EOF
{
    "Prompt": "🐶  pet>",
    "Style": {
        "Basic": ["on_default", "default"],
        "SavedSelection": ["bold", "on_yellow", "white"],
        "Selected": ["underline", "on_cyan", "black"],
        "Query": ["yellow", "bold"],
        "Matched": ["white", "bold"]
    }
}
EOF

You can now try a command to get started; go ahead and search the hashipets snippets:

$ pet search

Provided all went well, you should be browsing the snippet list and be able to search/filter them:

Screenshot showing browsing of hashipets snippets in pet

Browsing the hashipets snippets!

I hope this article and the projects in it have been useful to you.

Enjoy!