User Tools

Site Tools


pub:tech:dosh

dosh - The Simplest Build Tool on Earth

dosh is a minimal task runner pattern for shell scripts. Each dosh script is a standalone bash file where functions become tasks you can run from the command line.

Based on 8gears/do.

How It Works

A dosh script defines functions, then uses "$@" to execute whatever function name is passed as an argument:

snippet.bash
#!/usr/bin/env bash
 
build() {
    echo "Building..."
}
 
test() {
    echo "Testing..."
}
 
"$@"

Run it with:

snippet.bash
./dosh build    # runs build()
./dosh test     # runs test()

Sample Script

A complete sample dosh script is available: dosh.sh

Convention: Private Functions

Functions starting with _ are considered private/helper functions and won't appear in usage output or tab completion:

snippet.bash
_helper() {
    echo "I'm a helper"
}
 
build() {
    _helper
    echo "Building..."
}

Usage Output

Add this at the end of your dosh script to show available tasks when run without arguments:

snippet.bash
"$@"
[ "$#" -gt 0 ] || printf "Usage:\n\t./${SCRIPTNAME} %s\n" "($(compgen -A function | grep '^[^_]' | paste -sd '|' -))"

Tab Completion

Bash

Add the --completions handler to your dosh script, just before the "$@" line:

snippet.bash
if [[ "$1" == "--completions" ]]; then
    compgen -A function | grep '^[^_]'
    exit 0
fi
 
"$@"

Then add this to your ~/.bashrc:

snippet.bash
_dosh_complete() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    local script="${COMP_WORDS[0]}"
    COMPREPLY=($(compgen -W "$($script --completions 2>/dev/null)" -- "$cur"))
}
complete -F _dosh_complete dosh
complete -F _dosh_complete ./dosh

After reloading your shell (source ~/.bashrc), tab completion will work:

snippet.bash
./dosh bu<TAB>  # completes to ./dosh build

Zsh

The same --completions handler in your dosh script works for zsh. Add this to your ~/.zshrc:

snippet.zsh
_dosh_complete() {
    local completions
    completions=(${(f)"$($words[1] --completions 2>/dev/null)"})
    _describe 'tasks' completions
}
compdef _dosh_complete dosh
compdef _dosh_complete ./dosh

direnv Integration

A common pattern is to put dosh in bin/dosh and add bin to your PATH using direnv. This lets you run dosh build instead of ./bin/dosh build from anywhere in the project.

Example .envrc:

snippet.bash
PATH_add bin

See envrc for a more complete direnv setup.

With this pattern, add a completion registration for dosh (without the ./):

snippet.bash
complete -F _dosh_complete dosh      # bash
compdef _dosh_complete dosh          # zsh

Tips

  • Root access: Functions needing root should check for it and fail early
  • Working directory: Use BASEDIR to ensure consistent paths regardless of where the script is invoked from
  • Dependencies: Consider a deps or setup-dev task to install required tools
pub/tech/dosh.txt · Last modified: by james

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki