↖️ Show all posts

bb-maid Gets a Major UX Upgrade: Install via bbin, Tab Completion and Cleaner Commands

Tonight was one of those productive coding sessions where small improvements snowball into something really polished. I’ve been working on bb-maid, a Babashka script that helps keep directories clean by automatically removing expired folders, and we made some significant UX improvements that I’m excited to share.

What is bb-maid?

Before diving into the changes, let me quickly introduce bb-maid. It’s a Babashka script that works like a “digital housekeeper” for your filesystem. You create files named cleanup-maid-YYYY-MM-DD in directories you want to expire, and bb-maid will prompt you to delete those directories once the date passes. Think of it like expiration labels on food containers, but for your code directories.

The Journey: From Working to Delightful

Phase 1: Making it bbin-Compatible

The next challenge was making bb-maid installable via bbin, Babashka’s script manager. This required some structural changes:

Created proper namespace structure:

;; src/simonneutert/bb_maid.clj
(ns simonneutert.bb-maid
  (:require [bling.core :refer [bling callout]]
            [babashka.fs :as fs]))

(defn -main [& args]
  ;; Command handling
  )

Added dependency management:

;; deps.edn
{:paths ["src"]
 :deps {io.github.paintparty/bling {:mvn/version "0.4.2"}}}

Configured bbin entry point:

;; bb.edn
{:bbin/bin {bb-maid {:main-opts ["-m" "simonneutert.bb-maid"]}}}

Now users can install with a single command:

bbin install io.github.simonneutert/bb-maid

Phase 2: Adding the clean-in Command

The first improvement was adding a clean-in command to make it easier to create cleanup files:

bb-maid clean-in 7d

This parses duration strings (like 7d, 30d, 90d) and creates a cleanup-maid-YYYY-MM-DD file with the appropriate expiration date. No more manual date calculations!

Key features:

Phase 3: Adding Professional Tab Completion

This was the big one. Modern CLI tools need great tab completion, and we added support for both zsh and bash.

The Tab Completion Challenge

The first attempt had the completion file named bb-maid.zsh, but zsh wasn’t loading it. After some debugging, I discovered that zsh completion functions must be named with an underscore prefix (e.g., _bb-maid). This is a zsh convention that tells the completion system to auto-load the function.

What Gets Completed

The completion system is context-aware:

Phase 4: Cleaning Up the Command Structure

The final improvement was prompted by a great question: “Wouldn’t bb-maid clean /path/to/dir be cleaner?”

Absolutely! The original API was:

bb-maid /path/to/dir        # Implicit clean command
bb-maid clean-in 7d         # Explicit command

This inconsistency was confusing. Now it’s:

bb-maid clean /path/to/dir  # Explicit clean command
bb-maid clean-in 7d         # Explicit command

Much more intuitive and consistent with modern CLI conventions!

Technical Lessons Learned

1. Zsh Completion Naming Convention

Completion files must start with an underscore (_bb-maid) for auto-loading to work. This is a zsh convention that’s easy to miss if you’re new to writing completions.

2. Glob Qualifiers for Robust Paths

Using (N) in zsh glob patterns makes them optional:

fpath=(~/.gitlibs/*/completions(N) $fpath)

Without (N), zsh will error if the path doesn’t exist yet.

3. bbin Requires Proper Structure

For bbin compatibility, you need:

4. Context-Aware Completion is Delightful

Taking the time to make completion suggestions contextual (directories after clean, durations after clean-in) makes the tool feel polished and professional.


Read next ➡️