I’ve been using Howzit almost daily for years now. I made a bunch of upgrades to Howzit over the last month, including packaging it as a gem and completely refactoring the code. In the process it’s become pretty obvious that not many non-me people have actually tried it, and I really think they should, so I figured I’d at least make sure everyone understood what it does and how to use it.
Is Howzit Right for Me?
- Do you spend a good portion of your day in Terminal?
- Do you have different types of projects with different tools for building and deploying? Different processes/destinations for updating and publishing documentation?
- Do you ever come back to a project and find you’ve forgotten how you set it up and what you automated?
If you answered yes to all three questions, then you’re a prime candidate for Howzit. If you answered yes to the first two and no to the third, congratulations, you’re amazing. Either way, unless you checked all three, you can totally stop reading now. Go outside, enjoy life. Or whatever people who aren’t obsessed with the command line do.
The General Idea
The idea behind Howzit is simple: keep project notes and details in a single Markdown file, along with automations. In addition to documentation, the buildnotes.md
file can contain scripts and commands, functioning like a Makefile. It’s documentation plus automation. All with a friendly way to instantly view/run exactly the topic you need to know about without even having to cat
your notes.
howzit deploy
. As in “how does it deploy?” Yeah, you get it.
My favorite thing about using Howzit is the idea of universal commands. For example, howzit -r deploy
1 will automatically deploy any of my projects, even though every one of them deploys in a different way. Rsync, RubyGems, GitHub releases, git pushes… even the ones that use the same platform often have different requirements and commands for deploying. When I flesh out one of these processes, I document how it works and write a script to do everything that can be automated. It goes under the “Deploy” topic in the build notes file, along with step-by-step instructions, and then howzit -r deploy
takes care of the rest. If I’m curious and want to know exactly what’s happening, I can just run howzit deploy
and it will be explained to me.
Yes, I could write a script in every project and give it the same name, but Howzit lets me combine all of my scripts in one place using whatever language is most efficient, and I can include documentation that I can access right in the Terminal with syntax highlighting, pagination, and easy searching. And a single file can contain all the commands I need, and instead of having to develop help output for a complicated script with a bunch of switches/options, I just write Markdown notes.
Getting Started
First, install Howzit with gem install howzit
. If you’re using the system Ruby, you may get a permissions error, in which case you’ll need to run sudo gem install howzit
and enter your password.
You should also install
fzf
(brew install fzf
), which Howzit can use to display topics and previews in a menu when multiple matches are found for a search string orhowzit --select
is run. Optional, but very nice.
Next, cd
into a project directory (the top level of your git repo, for example) and run howzit --create
. This will ask you a couple of questions and then write out a skeleton build note. You can modify the name if you want to — the only requirement is that it start with “build” or “howzit” and have an extension of “md” or “txt”. I have a global .gitignore
setting that includes buildprivate.md
, so if I use that name in a project, the build note never gets added to version control, in case I don’t want to share it publicly.
Now open the build note in an editor and fill in the info you have in the moment. You can do this quickly with howzit --edit
, but if you want to use something other than $EDITOR, you’ll need to configure it.
Give each topic a heading using two or more hashes, then just use Markdown to write out notes. You can add commands using @directives or run blocks. The headlines you give each topic are how you’ll access them from the command line. It’s easiest if you give them all unique names, as Howzit can fuzzy/partial match and you can abbreviate a command to its shortest unique permutation, e.g. howzit dpl
to run howzit deploy
. Conversely, you can use similar names to be able to run multiple topics with a single command using fuzzy matching or wildcards.
Now, every time you figure something out or use a repetitive sequence of commands, add documentation and scripts to the build note for future reference and automation.
Configuration
You can edit your config file by running howzit --edit-config
. Here’s the config I use:
:color: true
:config_editor: subl
:editor: subl
:header_format: block
:highlight: true
:highlighter: mdless
:include_upstream: true
:log_level: 0
:matching: fuzzy
:multiple_matches: choose
:output_title: false
:pager: auto
:paginate: true
:show_all_code: false
:show_all_on_error: false
:wrap: 0
If you have mdcat
installed (available through Homebrew), you should try both that and mdless
as the :highlighter:
and see which you like better. mdless
(one of my own projects) is included and I like certain things about it better, but it has some quirks. If you have pygmentize
installed, mdless
will highlight fenced code, which is nice.
The :include_upstream: true
setting allows Howzit to look in parent directories for additional build notes, incorporating their topics into the current list. It’s somewhat useful when all subdirectories of a parent folder are the same kind of project and would have common tasks. The feature has been mostly superseded by templates, though, which I’ll talk about next.
The rest of the options are explained in the wiki for the cases where they key names aren’t self-evident.
Templates
Once you get going with templates, setting up a new project is a breeze. Any time a task or topic can be repeated across multiple projects, stick it in a template and then just add that template to related projects. You can even define variables in each project to make the included topics dynamic.
To create a template, run howzit --edit-template NAME
, where name is the short name you’ll refer to the template by. Edit it as you would a regular build note file (level 2+ headers and content). Then in a project where the topics in the template apply, just add at the top:
template: git,gem
My git template includes tasks for things like automating git-flow releases, doing repo cleanup, and updating submodules. I can have variables defined for things such as the develop branch name, in case it differs from project to project2. In the template I can use [%develop_branch:develop]
, and in the metadata for a build note I can include develop_branch: dev
. (The :develop
part of the template placeholder defines a default, used if the variable isn’t defined in the metadata.)
You can make certain metadata required when including a template by adding required: my_key
to the metadata of the template. If you try to display/execute the build note and it doesn’t have the necessary metadata, it will give you an error. By the way, all of these keys can have multiple values, just separate with commas.
You can also include only certain topics from a template in your build note using template_name[topic 1|topic 2]
. Include one or more topics separated with pipes (|
). Partial matches work, and you can also use *
as a wildcard to include multiple topics with common names.
You can get a list of all templates with --templates
. This will show you the template name, what topics it includes, and what metadata can/must be defined to use it.
Prerequisites
In cases where you can’t automate certain steps of a topic, you can remind yourself of any prerequisites and post-procedure tasks using @before
and @after
tags.
Anything in a @before
/@end
block will get presented before a topic executes, requiring confirmation before proceeding.
@before
- Have you committed all changes with changelog-friendly messages?
@end
Anything in an @after
/@end
block just gets displayed after the topic runs, serving as a reminder of any manual tasks that need handling.
@after
- cd to docs repo and generate a release with matching version number
@end
You can have multiple of either block; they’ll be concatenated when the topic is run.
Aliases
I use a few shell aliases with Howzit.
First, there’s just how=howzit
to shorten the commands. Combined with fuzzy topic matching, I can just type how git
to see all of the pertinent information about the git setup for the project — branching strategy, origin urls, etc.
Second, I have an alias (a function, actually) called bld
that essentially just runs howzit -r [arg 1] -- [other args]
. You can pass positional arguments to Howzit by adding --
on the command line; anything after the double dash is interpreted as arguments that can be used in scripts with $1
, $2
, etc. (or $*
). So my first argument is always the topic, and because I don’t need spaces for fuzzy matching, I can make any topic into one word (e.g. “Deploying the Beta” can be called with just bld dbeta
).
By the way, there are shell completions available for Fish. I haven’t taken the time to create them for other shells yet, but if you’re on Fish, well, there you go.
Hooks and Links
You build note files make great central points for “hooking” all other related items. On macOS, you can just run howzit --hook
to copy a Markdown link to the main file, ready to paste into Hook with another item (mind maps, emails, nvUltra notes, TaskPaper lists, etc.), or just to add to a central note in whatever your note-taking app is.
So there you have it. If you read this far, then Howzit is probably of interest to you and I recommend checking out the wiki for more details. Have fun documenting and automating!