Handy multitool that happens to be mostly Go
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
cmd/leatherman
pkg
tool
.gitignore
.travis.yml
Makefile
README.mdwn
go.mod
go.sum

README.mdwn

Leatherman - fREW's favorite multitool

This is a little project simply to make trivial tools in Go effortless for my personal usage. These tools are almost surely of low utility to most people, but may be instructive nonetheless.

Project layout should be familiar to most Go programmers, with the exception of the /tool/ directory. This directory contains the tools which are effectively main, but have their own names. There are enough tools at this point that accidentally reusing package variables is a real risk, hence the package-per-tool structure.

I have CI/CD to build this into a single binary and an explode tool that builds symlinks for each tool in the busybox style.

I have add automation in my dotfiles to pull the latest binary at install time and run the explode tool.

Installation

Here's a copy pasteable script to install the leatherman on OSX or Linux:

OS=$([ $(uname -s) = "Darwin" ] && echo "-osx")
LMURL="$(curl -s https://api.github.com/repos/frioux/leatherman/releases/latest |
   grep browser_download_url |
   cut -d '"' -f 4 |
   grep -F leatherman${OS}.xz )"
mkdir -p ~/bin
curl -sL "$LMURL" > ~/bin/leatherman.xz
xz -d -f ~/bin/leatherman.xz
chmod +x ~/bin/leatherman
~/bin/leatherman explode

This asssumes that ~/bin is in your path. The explode command will create a symlink for each of the tools listed below.

Usage

Each tool takes different args, but to run a tool you can either use a symlink (presumably created by explode):

$ echo "---\nfoo: 1" | yaml2json
{"foo":1}

or use it as a subcommand:

echo "---\nfoo: 1" | leatherman yaml2json
{"foo":1}

Current tools

addrs

$ <someaddrs.txt addrs "$HOME/mail/gmail.sent/cur/*" >sortedaddrs.txt

Reads emails (in the mutt addrbook format, see below) on stdin and sorts them based on when they were most recently sent to.

addrspec-to-tabs

Converts email addresses from the standard format ("Hello Friend" <foo@bar>) to the mutt (?) address book format, ie tab separated fields.

Note that this new version ignores the comment because, after actually auditing my addressbook, most comments are incorrectly recognized by all tools. (for example: <5555555555@vzw.com> (555) 555-5555 should not have a comment of (555).)

backlight

Faster version of xbacklight by directly writing to /sys. Example:

Increase by 10%:

$ backlight 10

Decrease by 10%:

$ backlight -10

clocks

My personal, digital, wall of clocks.

csv2json

Reads CSV on stdin and writes JSON on stdout; first line of input is the header, and thus the keys of the JSON.

csv2md

Reads CSV on stdin and writes Markdown on stdout.

debounce

Powerful tool for debouncing lines of input.

dump-mozlz4

Dump the contents of a mozlz4 (aka jsonlz4) file commonly used by Firefox. Just takes the name of the file to dump and writes to standard out.

defer-lwn

Create undefer files for any lines containing a markdown link to LWN. Lines will be added in no particular order. Lines not containing links (or otherwise running into errors) will be printed to standard out, with errors going to standard error.

expand-url

Reads text on STDIN and writes the same text back, converting any links to Markdown links, with the title of the page as the title of the link. If you set MOZ_COOKIEJAR to the path of your cookies.sqlite it will use those cookies when loading the page.

export-bamboohr

Exports entire company directory as JSON.

export-bamboohr-tree

Exports company org chart as JSON.

fn

Create persistent functions by actually writing scripts. Example usage:

fn count-users 'wc -l < /etc/passwd'

gen-pass

Little tool for generating bcrypt hashes.

group-by-date

Creates time series data by counting lines and grouping them by a given date format.

netrc-password

Pass hostname and login and this will print the password for the account.

pomotimer

pomotimer 2.5m

or

pomotimer 3m12s

Originally a timer for use with the pomodoro technique. Handy timer in any case since you can pass it arbitrary durations, pause it, reset it, and see it's progress.

prepend-emoji-hist

alluni.pl | prefix-emoji-hist ~/.uni_history

Prints out the deduplicated lines from the passed file, converting characters to unicode names, and then printing out the lines from STDIN, filtering out what's already been printed. Note that alluni.pl is in my dotfiles

render-mail

Ghetto tool to render email with a Local-Date included, if Date is not already in local time.

replace-unzip

Extracts zipfiles, but does not extract .DS_Store or __MACOSX/. Automatically extracts into a directory named after the zipfile if there is not a single root for all files in the zipfile.

rss

Minimalist rss client. Outputs links as markdown on STDOUT. Takes url to feed and path to state file. Example usage:

$ rss https://blog.afoolishmanifesto.com/index.xml afm.json
[Announcing shellquote](https://blog.afoolishmanifesto.com/posts/announcing-shellquote/)
[Detecting who used the EC2 metadata server with BCC](https://blog.afoolishmanifesto.com/posts/detecting-who-used-ec2-metadata-server-bcc/)
[Centralized known_hosts for ssh](https://blog.afoolishmanifesto.com/posts/centralized-known-hosts-for-ssh/)
[Buffered Channels in Golang](https://blog.afoolishmanifesto.com/posts/buffered-channels-in-golang/)
[C, Golang, Perl, and Unix](https://blog.afoolishmanifesto.com/posts/c-golang-perl-and-unix/)

sm-list

List all of the available Sweet Maria's coffees as json documents per line. Here's how you might see the top ten coffees by rating:

$ sm-list | jq -r '[.Score, .Title, .URL ] | @tsv' | sort -n | tail -10

ssh-quote

Prepares the arguments such that they can be pasted into an ssh command safely. For example:

$ ssh-quote ls 'f*f'
'sh -c '\''ls '\''\'"''"'f*f'\''\'\'

undefer

Takes a directory argument, prints contents of each file named before the current date, and then deletes the file.

If the current date were 2018-06-07 the starred files would be printed and then deleted:

 * 2018-01-01.txt
 * 2018-06-06-awesome-file.md
   2018-07-06.txt

yaml2json

Reads YAML on stdin and writes JSON on stdout.

Debugging

In an effort to make debugging simpler, I've created three ways to see what leatherman is doing:

  1. LMTRACE=$somefile will write an execution trace to $somefile.
  2. LMPROF=$somefile will write a cpu profile to $somefile.
  3. The pprof http endpoint is exposed on localhost:6060/debug/pprof; the port can be overridden by setting LMHTTPPROF=$someport

Since so many of the tools are short lived my assumption is that the execution trace will be the most useful.