Hoi, a command line task runner built with Rust

By Kevin , May 7th, 2025

During covid lockdowns I had several projects in my spare time to keep me busy. One of them was teaching myself to learn how to read sheet music. Another was building an LCD screen marquee of data powered by a Raspberry Pi 3. One was to learn how to write my own programming language using the book "Crafting Interpreters" by Robert Nystrom. The book uses Java I believe as a teaching tool, but I wanted to learn Rust and do it that way. 

First, I wanted to do a small project in Rust to get acquainted with the language before, you know, writing an interpreter with it. I chose to mimic a program we were using at the time called Ahoy!, a task runner written in Go. I figure this would be straightforward enough to do in Rust.

Objectives:

  • Ability to define 'commands' in YAML
  • Ability to initialize a new YAML configuration file in a directory
  • Ability to have a global configuration file for 'always available' commands
  • Ability to use bash or shell, and or change the execution options for it
  • Release for Windows, Mac and Linux
  • Publish package to cargo, apt, homebrew, dnf, and other managers 

Every Saturday or Sunday morning I would go through my Rust book and work at it. I made decent progress, up to the point where I wanted to execute a command with a different entrypoint and got stuck. As with most events in life, I had to shelve it and move on to other work, especially as lockdown restrictions lifted and we started getting back to normal.

I never forgot about it though. I wanted to pick it back up in the last few weeks to see if I could get through the problem. Turns out what I was stuck on actually worked, I was just reading the output incorrectly.

Anyway, I got some inspiration and was able to work through remaining issues, refactor some of the code, and add some new features I hadn't thought of at the time. I moved the project out of my GitLab account to GitHub to take advantage of GitHub Actions (I unfortunately had a lot of trouble trying to publish to cargo with GitLab CI). After moving to GitHub Actions, I was able to work through that part of it pretty quickly.

In the last week, I was able to begin publishing releases to Cargo so anyone could install it with cargo install hoi. It was really cool to see this install and run on both my Linux and MacOS machines.

Image
screenshot of hoi

You can view the repo and package here:

There are almost 1000 downloads already, which is mind blowing. It is a small utility project, I am curious if it helps people out!

Why Hoi?

When someone creates a new command, script, or workflow, sometimes they can be very long and difficult to remember - and harder to execute consistently even with the best of documentation. In short, tools like this should help the least technical members of your team take advantage of the same powerful tools as the top technical members.

Meaning, if they had to perform tasks like syncing a database locally, executing several scripts in Docker, or doing a sequence of events - instead of struggle through a lot of technical details they can simply type:

hoi (command)

Consider a scenario where you need to run a Gulp command, move the resulting files around in the project, and clear the Drupal cache. If you do this all the time it may be second nature, but its difficult to onboard people or for less technical users. Instead, you can write that into a .hoi.yml file:

  build-theme:
    cmd: |
      echo "Building Drupal theme assets."
      docker compose run --rm node ./node_modules/.bin/gulp build --no-watch --env production
      cp ./frontend/build/css/index-generated.css ./docroot/themes/custom/mytheme/css/index-generated.css
      cp ./frontend/build/css/index-generated.css.map ./docroot/themes/custom/mytheme/css/index-generated.css.map
      cp ./frontend/build/js/index-generated.js ./docroot/themes/custom/mytheme/js/index-generated.js
      cp ./frontend/build/js/index-generated.js.map ./docroot/themes/custom/mytheme/js/index-generated.js.map
      cp ./frontend/build/js/libraries-generated.js ./docroot/themes/custom/mytheme/js/libraries-generated.js
      cp ./frontend/build/js/libraries-generated.js.map ./docroot/themes/custom/mytheme/js/libraries-generated.js.map
      hoi drush @myproject.local cr
    description: Runs the Gulp build process and copies the assets into the right areas of the project, then clears the cache.

Then, to do all that work, someone just executes hoi build-theme. Thats it. They can contribute more commands back by writing them in .hoi.yml and committing them to their project.

It felt good to get it out the door and publish it in a language I don't get to touch often but admire from a distance. I hope people find it useful!

Tags