Keeping track of your build systems so you don’t have to

Howzit is a tool that allows you to keep Markdown-formatted notes about a project’s tools and procedures. It functions as an easy lookup for notes about a particular task, as well as a task runner to automatically execute appropriate commands.


  • Match topic titles with any portion of title
  • Automatic pagination of output, with optional Markdown highlighting
  • Use @run(), @copy(), and @open() to perform actions within a build notes file
  • Use @include() to import another topic’s tasks
  • Use fenced code blocks to include/run embedded scripts
  • Sets iTerm 2 marks on topic titles for navigation when paging is disabled
  • Inside of git repositories, howzit will work from subdirectories, assuming build notes are in top level of repo

Getting Started

Howzit is a simple, self-contained script (at least until I get stupid and make a gem out of it).


  • Ruby 2.4+ (It probably works on older Rubys, but is untested prior to 2.4.1.)
  • Optional: if bat is available it will page with that
  • Optional: mdless or mdcat for formatting output


One-Line Install

You can install howzit by running:

curl -SsL ''|bash

Manual Install

Clone the repo or just download the self-contained script. Save the script as howzit to a folder in your $PATH and make it executable with:

chmod a+x howzit

Anatomy of a Build Notes File

Howzit relies on there being a file in the current directory with a name that starts with “build” and an extension of .md, .txt, or .markdown, e.g. This note contains topics such as “Build” and “Deploy” with brief notes about each topic in Markdown (or just plain text) format.

The topics of the notes are delineated by Markdown headings, level 2 or higher, with the heading being the title of the topic. I split all of mine apart with h2s. For example, a short one from the little website I was working on yesterday:

## Build

gulp js: compiles and minifies all js to dist/js/main.min.js

gulp css: compass compile to dist/css/

gulp watch

gulp (default): [css,js]

## Deploy

gulp sync: rsync /dist/ to scoffb.local

## Package management


## Components

- UIKit

Howzit expects there to only be one header level used to split topics. Anything before the first header is ignored. If your topics use h2 (##), you can use a single h1 (#) line at the top to title the project.


You can include commands that can be executed by howzit. Commands start at the beginning of a line anywhere in a topic. Only one topic’s commands can be run at once, but all commands in the topic will be executed when howzit is run with -r. Commands can include any of:

  • @run(COMMAND)

    The command in parenthesis will be executed as is from the current directory of the shell

  • @copy(TEXT)

    On macOS this will copy the text within the parenthesis to the clipboard. An easy way to offer a shortcut to a longer build command while still allowing it to be edited prior to execution.

  • @open(FILE|URL)

    Will open the file or URL using the default application for the filetype. On macOS this uses the open command, on Windows it uses start, and on Linux it uses xdg-open, which may require separate installation.

  • @include(TOPIC)

    Includes all tasks from another topic, matching the name (partial match allowed) and returning first match.

Run blocks (embedded scripts)

For longer scripts you can write shell scripts and then call them with @run( For those in-between cases where you need a few commands but aren’t motivated to create a separate file, you can use fenced code blocks with run as the language.

# Commands...

The contents of the block will be written to a temporary file and executed with /bin/sh -c. This means that you need a hashbang at the beginning to tell the shell how to interpret the script. If no hashbang is given, the script will be executed as a sh script.


```run Just Testing
echo "Just needed a few lines"
echo "To get through all these commands"
echo "Almost there!"
say "Phew, we did it."

Multiple blocks can be included in a topic. @commands take priority over code blocks and will be run first if they exist in the same topic.


When running commands in a topic, you can use a double dash (--) in the command line (surrounded by spaces) and anything after it will be interpreted as shell arguments. These can be used in commands with $ placeholders. $1 represents the first argument, counting up from there. Use $@ to pass all arguments as a shell-escaped string.

For example, the topic titled “Test” could contain an @run command with placeholders:

## Test
@run(./ $@)

Then you would run it on the command line using:

howzit -r test -- -x "arg 1" arg2

This would execute the command as ./ -x arg\ 1 arg2.

Placeholders can be used in both commands and run blocks. If a placeholder doesn’t have an argument supplied, it’s not replaced (e.g. leaves $2 in the command).

Using howzit

Run howzit on its own to view the current folder’s buildnotes.

Include a topic name to see just that topic, or no argument to display all.

howzit build

Use -l to list all topics.

howzit -l

Use -r to execute any @copy, @run, or @open commands in the given topic. Options can come after the topic argument, so to run the commands from the last topic you viewed, just hit the up arrow to load the previous command and add -r.

howzit build -r

Other options:

Usage: howzit [OPTIONS] [TOPIC]

    -c, --create                     Create a skeleton build note in the current working directory
    -e, --edit                       Edit buildnotes file in current working directory using
    -L, --list-completions           List topics for completion
    -l, --list                       List available topics
    -m, --matching TYPE              Topic matching: exact, partial (default), beginswith, or fuzzy
    -R, --list-runnable              List topics containing @ directives (verbose)
    -r, --run                        Execute @run, @open, and/or @copy commands for given topic
    -s, --select                     Select topic from menu
    -T, --task-list                  List topics containing @ directives (completion-compatible)
    -t, --title                      Output title with build notes
    -w, --wrap COLUMNS               Wrap to specified width (default 80, 0 to disable)
        --edit-config                Edit configuration file using
        --title-only                 Output title only
        --[no-]color                 Colorize output (default on)
        --[no-]md-highlight          Highlight Markdown syntax (default on), requires mdless or mdcat
        --[no-]pager                 Paginate output (default on)
    -h, --help                       Display this screen
    -v, --version                    Display version number


Some of the command line options can be set as defaults. The first time you run howzit, a YAML file is written to ~/.config/howzit/howzit.yaml. You can open it in your default editor automatically by running howzit --edit-config. It contains the available options:

:color: true
:highlight: true
:paginate: true
:wrap: 80
:output_title: false
:highlighter: auto
:pager: auto
:matching: partial

If :color: is false, output will not be colored, and markdown highlighting will be bypassed.

If :color: is true and :highlight: is true, the :highlighter: option will be used to add Markdown highlighting.

If :paginate: is true, the :pager: option will be used to determine the tool used for pagination. If it’s false and you’re using iTerm, “marks” will be added to topic titles allowing keyboard navigation.

:highlighter: and :pager: can be set to auto (default) or a command of your choice for markdown highlighting and pagination.

:matching: can be “partial”, “beginswith”, “fuzzy” or “exact” (see below).


All matching is case insensitive. This setting can be overridden by the --matching TYPE flag on the command line.

  • :matching: partial

    Partial is the default, search matches any part of the topic title.

    Example: howzit other matches ‘Another Topic’.

  • ‘:matching: beginswith`

    Matches from the start of the title.

    Example: howzit another matches ‘Another Topic’, but neither ‘other’ or ‘topic’ will.

  • :matching: fuzzy

    Matches anything containing the search characters in order, no matter what comes between them.

    Example: howzit asct matches ‘Another Section’

  • :matching: exact

    Case insensitive but must match the entire title.

    Example: Only howzit another topic will match ‘Another Topic’


If set to auto, howzit will look for pagers in this order, using the first one it finds available:

  • $PAGER
  • bat
  • less
  • more
  • cat
  • pager

If you’re defining your own, make sure to include any flags necessary to handle the output. If you’re using howzit’s coloring, for example, you need to specify any options needed to display ANSI escape sequences (e.g. less -r).


If set to auto howzit will look for markdown highlighters in this order, using the first it finds available:

  • mdcat
  • mdless

If you’re combining a highlighter with howzit’s pagination, include any flags needed to disable the highlighter’s pagination (e.g. mdless --no-pager).

Shell Integration

I personally like to alias bld to howzit -r. If you define a function in your shell, you can have it default to “build” but accept an alternate argument. There’s an example for Fish included, and in Bash it would be as simple as howzit -r ${1:build}.

For completion you can use howzit -L to list all topics, and howzit -T to list all “runnable” topics (topics containing an @directive or run block). Completion examples for Fish are included in the fish directory.

Similar Projects

There are a few projects that tackle the same concept (a Markdown makefile). Most of them are superior task runners, so if you’re looking for a make replacement, I recommend exploring the links above. What I like about howzit (and what keeps me from switching) is that it’s documentation-first, and that I can display the description for each topic on the command line. The others also don’t have options for listing topics or runnable tasks, so I can’t use completion (or my cool script that adds available tasks to my Macbook Pro Touch Bar…). But no, I don’t think howzit is as good an overall task runner as mask or maid.


  • Recognize header hierarchy, allow showing/running all sub-topics


Brett Terpstra -


This project is licensed under the MIT License - see the file for details.


Download the howzit script on GitHub.



  • Code refactoring/cleanup
  • Rename “sections” to “topics”
  • If no match found for topic search, only show error (:show_all_on_error: false option)


  • Fix removal of non-alphanumeric characters from titles
  • -s/–select option to display a menu of all available topics
  • Allow arguments to be passed after -- for variable substitution
  • Allow –matching TYPE to match first non-ambigous keyword match


  • –matching [fuzzy,beginswith,partial,exact] flag
  • –edit-config flag
  • sort flags in help


  • After consideration, remove full fuzzy matching. Too many positives for shorter strings.


  • Add full fuzzy matching for topic titles
  • Add @include(TOPIC) command to import another topic’s tasks


  • Add config file for default options


  • Use system instead of exec to allow multiple @run commands
  • Add code block runner


  • Add -e/--edit flag to open build notes in $EDITOR


  • Use exec for @run commands to allow interactive processes (e.g. vim)


  • Add option for outputting title with notes
  • Add option for outputting note title only


  • Fix for “topic not found” when run with no arguments


  • Reorganize and rename long output options
  • Fix wrapping long lines without spaces


  • Add -R switch for listing “runnable” topics
  • Add -T switch for completion-compatible listing of “runnable” topics
  • Add -L switch for completion-compatible listing of all topics


  • Allow topic matching within title, not just at start
  • Remove formatting of topic text for better compatibility with mdless/mdcat
  • Add @run() syntax to allow executable commands
  • Add @copy() syntax to copy text to clipboard
  • Add @url/@open() syntax to open urls/files, OS agnostic (hopefully)
  • Add support for mdless/mdcat
  • Add support for pager
  • Offer to create skeleton buildnotes if none found
  • Set iTerm 2 marks for navigation when paging is disabled
  • Wrap output with option to specify width (default 80, 0 to disable)

  • Support
  • GitHub
  • Download

Speaking of howzit…

Related Projects