# 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](https://github.com/8gears/do). ## How It Works A dosh script defines functions, then uses `"$@"` to execute whatever function name is passed as an argument: ```bash #!/usr/bin/env bash build() { echo "Building..." } test() { echo "Testing..." } "$@" ``` Run it with: ```bash ./dosh build # runs build() ./dosh test # runs test() ``` ## Sample Script A complete sample dosh script is available: [dosh.sh](dosh.sh) ## Convention: Private Functions Functions starting with `_` are considered private/helper functions and won't appear in usage output or tab completion: ```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: ```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: ```bash if [[ "$1" == "--completions" ]]; then compgen -A function | grep '^[^_]' exit 0 fi "$@" ``` Then add this to your `~/.bashrc`: ```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: ```bash ./dosh bu # completes to ./dosh build ``` ### Zsh The same `--completions` handler in your dosh script works for zsh. Add this to your `~/.zshrc`: ```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`: ```bash PATH_add bin ``` See [envrc](https://code.librehq.com/james/envrc) for a more complete direnv setup. With this pattern, add a completion registration for `dosh` (without the `./`): ```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