Contents

espanso!

I’m always looking for new ways to improve my workflow and cut down on repetitive tasks and shell commands. I think it was around January when superhero1 introduced a new tool he had found - espanso created by Federico Terzi.

What is it?

Espanso is an open source text expander on steroids. This won’t be an extensive overview of the program but I’ll touch on some of its core features.

The image below illustrates how espanso’s base functionality works. From the Getting Started Doc: “espanso works by detecting your keypresses and replacing them when they match a specific keyword, called trigger.”

Image of espanso matches

Matches

Are you tired of typing python -c 'import pty;pty.spawn("/bin/bash")' every time you land on a box to get a usable shell? Why not just type :pty! What about a way to automagically sync stty rows and cols? 😃

A couple of examples to get your gears turning…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
matches:
  # Upgrade shell
  - trigger: ":pty"
    replace: "python -c 'import pty;pty.spawn("/bin/bash")'"
    
  # Append my public key to authorized_keys. 
  # $|$ is a 'cursor hint' that will place your cursor there after the expansion
  - trigger: ":addkey"
    replace: "echo \"{{PUBKEY}}\" >> /home/$|$/.ssh/authorized_keys"

  # Output tun0 IP
  - trigger: ":t0"
    replace: "{{TUN0}}"

You can define global variables from shell output and use them for all your matches similar to environment variables.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
global_vars:
  - name: "PUBKEY"
    type: "shell"
    params:
      cmd: "echo ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK0wmN/Cr3JXqmLW7u+g9pTh+wyqDHpSQEIQczXkVx9x"
      
  # Extract tun0 ipv4 address
  - name: "TUN0"
    type: "shell"
    params:
      cmd: "ip a s tun0 | grep 'inet ' | awk -F ' ' '{print $2}' | cut -d'/' -f 1"

Clipboard Extension

The Clipboard Extension allows you use the current clipboard content for a match.

Here’s an example to take what’s currently on your clipboard, base64 encodes the content (excluding the trailing new line), then puts the base64 encoded string back onto your clipboard. It’s a weird example but it might be useful in a pinch.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  # Clipboard -> base64 encode -> clipboard
  - trigger: ":cb64"
    replace: "{{shell}}"
    vars:
      - name: clipboard
        type: clipboard
      - name: shell
        type: shell
        params:
          cmd: "echo -n $ESPANSO_CLIPBOARD | base64 | xclip -sel clip"

Check out the documentation on matches here: https://espanso.org/docs/matches/

Final thoughts

Sure, text expanders aren’t a new concept but are the others written in Rust 🦀, open source, and cross-platform? I doubt it! All jokes aside, I’ve enjoyed using this program over the past few months. I haven’t gotten into using some of the more interesting features such as image matches or forms but I plan to. I do use the passive mode and it is pretty awesome.

If anything, I hope this gets your gears turning on how you could improve your productivity as you hop around different hosts and VMs. The portability of this program really sold me. I plan on releasing an espanso package geared towards CTF players soon. I’ll post on twitter when it’s available.