How I Automated My Dotfiles Screenshots

How I automated taking screenshots of my terminal environment

automationdotfilesscreenshotsmacappleautomator
Author avatar
Albin Groen

Posted 2021-06-16


Recently I've been working a lot on my terminal environment and dotfiles structure. My strategy has been to keep everything on GitHub so I can just pull it down when I want to start working on a new machine. While doing this, I also wanted to show what everything looks like in the README file, so I created a little automation that opens a new Tmux session, splits into a couple of sections, opens a few applications, and then take a screenshot that gets uploaded to Cloudinary and then copied to my clipboard.

Now, to do this I started by creating a new Application in the Automator app for Mac. I started by dragging in an Applescript block. In this script, I start with opening Kitty (my terminal emulator of choice), and then open everything, before I take a screenshot using Cleanshot. After I'm done with this, I run a sub-application that basically just runs a Node.js script that uploads the newly taken screenshot to Cloudinary and then copies it to the system clipboard.

Take screenshot

This script is a little bit finicky since what it mostly relies on is the use of manually executing keystrokes and key codes, and adding a couple of delay statements in between time-intensive tasks. This can unfortunately sometimes result in a Tmux split missing, or the screenshot turning out to be taken on a browser or finder window, instead of the actual Terminal. In most cases though, the script works, and then it's really nice to use.

on run {input, parameters}

    tell application "kitty"
    -- Open Kitty terminal emulator
        activate

        tell application "System Events"
            tell process "kitty"
                delay 2

                keystroke "a" using control down
                keystroke ":new"
                key code 36

                keystroke "cd && vim tracing.ts"
                key code 36

                keystroke "a" using control down
                keystroke "v"

                keystroke "clear && neofetch"
                key code 36

                keystroke "a" using control down
                keystroke "-"

                keystroke "htop"
                key code 36

                delay 4

                key code 26 using {shift down, command down}
                delay 1
                key code 36

                delay 2

                keystroke "a" using control down
                keystroke "x"
                keystroke "y"

                keystroke "a" using control down
                keystroke "x"
                keystroke "y"

                keystroke "a" using control down
                keystroke "x"
                keystroke "y"

                keystroke "w" using command down
            end tell
        end tell
    end tell
    return input
end run

Upload screenshot

What this script does is that it looks inside of the screenshot folder for the latest screenshot, and then uploads it to Cloudinary using its Node.js SDK. After it's been successfully uploaded and sent back in the callback, we take the secure URL of the image and copies it to the system clipboard.

import { v2 as cloudinary } from "cloudinary";
import clipboardy from "clipboardy";
import dotenv from "dotenv";
import fs from "fs";

dotenv.config();

cloudinary.config({
  cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
  api_secret: process.env.CLOUDINARY_API_SECRET,
  api_key: process.env.CLOUDINARY_API_KEY,
});

function main() {
  console.log("Uploading image...");

  const dirPath = "/Users/albin/Screenshots";
  const files = fs
    .readdirSync(dirPath, "utf8")
    .filter((file) => !file.startsWith("."));

  const imagePath = [dirPath, files[files.length - 1]].join("/");

  cloudinary.uploader.upload(imagePath, (err, res) => {
    if (err) {
      return console.log(err);
    }

    if (res) {
      fs.rmSync(imagePath);

      clipboardy.writeSync(res.secure_url);
      return console.log("Done!");
    }

    console.log("No result returned");
  });
}

main();

After running the script, here's what the screenshot turned out like:

Terminal screenshot

If you made it all the way down here, consider following me on twitter @albingroen. Have a nice day!