ltag: A little CLI tool for tagged text searching
Tags: showdev, go, cli, fzf
Published: 2023-10-27 15:14:40

---
title: ltag: A little CLI tool for tagged text searching
published: true
description: I wrote a CLI tool in Go that will let you add tags to plaintext lines. This will help you search for the text better.
tags: #showdev #go #cli #fzf
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2023-10-27 13:48 +0000
---

## The Problem

I have a command reference. It's a text file with lots of CLI commands I've written down because I don't want to memorise them all. For example here's a bunch of network-related commands:

```
nslookup -type=ns example.com
nslookup -type=txt example.com
nslookup -type=cname example.com
nslookup example.com 1.1.1.1
dig example.com txt
dig example.com cname
netstat --tcp
netstat --program
netstat --listening
```

When I want to look up a command, I don't always remember the actual command I want. Let's suppose I need to do a DNS lookup. I might not remember that I need `dig` or `nslookup`. Or I might just need something to do with networking. How can I search for all DNS commands or networking commands?

## Halfway There: A Better Command Reference

I can add headings and sub-headings to the list above. Each heading starts with a hashtag to differentiate it from the actual commands.

```
# Networking
# DNS
nslookup -type=ns example.com
nslookup -type=txt example.com
nslookup -type=cname example.com
nslookup example.com 1.1.1.1
dig example.com txt
dig example.com cname
# See processes and ports used
netstat --tcp
netstat --program
netstat --listening
```

This is better, but I'd still need to search for DNS and scan over the following lines to find the command I want. __A better way is to associate a bunch of tags with each line. Each tag would place the line in some category. A DNS category, a networking category.__ But manually writing "#dns" after every DNS command in my list would be tedious. It would also pollute the command reference with tags everywhere.

## The Solution: ltag + fzf

So instead I created a tool read the above text, append the heading to every line as a tag, and print out the result. That would convert the above text to the following:

```
nslookup -type=ns example.com #networking #dns
nslookup -type=txt example.com #networking #dns
nslookup -type=cname example.com #networking #dns
nslookup example.com 1.1.1.1 #networking #dns
dig example.com txt #networking #dns
dig example.com cname #networking #dns
netstat --tcp #networking #see-processes-and-ports-used
netstat --program #networking #see-processes-and-ports-used
netstat --listening #networking #see-processes-and-ports-used
```

I call this tool "ltag", short for "Line tag". It's written in Go. Here's the git repository: [mebble/ltag](https://github.com/mebble/ltag/).

With tagging out of the way, I now have the ability to search.

The CLI search tool I use is [fzf](https://github.com/junegunn/fzf). fzf takes in any text stream and spins up a TUI for you to fuzzy search through the text. I can pipe my tool's output to fzf and violà, I can now search by command and by tag!

I still have one problem though. The purpose of looking up commands is so that I can run them. When I select a command through fzf, the tags associated with that command also get selected. I'd like to get rid of these tags once I've found the command I want. So my tool is also able to remove tags from the selected line.

I can now do a quick command lookup using a shell alias:

```bash
alias cl="cat ~/.cmd-reference.txt | ltag | fzf | ltag --trim | pbcopy"
```

## Beyond a Command Reference

This tool could help you search through any list of things. And the list doesn't have to be in a text file. ltag reads from standard input, so you can pipe the output of any command to it.


This is my first Go project, and I'm glad I found a way to create something actually useful. So here it is, hope you find it useful as well.