Argc is also a command runner for Bash. Instead of writing argument parsing for every project task, you put the tasks in an Argcfile.sh, and argc handles routing, help, validation, and completion.
This guide covers the runner-specific features. For the underlying tag reference, see Comment Tags.
Recipes are stored in a file named Argcfile.sh:
argc --argc-create - build test- is an alias for Argcfile.sh. The command creates a boilerplate file:
#!/usr/bin/env bash
set -e
# @cmd
build() {
echo TODO build
}
# @cmd
test() {
echo TODO test
}
# See more details at https://github.com/sigoden/argc
eval "$(argc --argc-eval "$0" "$@")"Run a recipe with argc:
argc build
argc testargc searches for Argcfile.sh in the current directory and its parents, so you can run it from a subdirectory. The name is matched case-insensitively, and the .sh suffix is optional, so Argcfile, argcfile.sh, and ARGCFILE are all recognized.
A recipe is a normal Bash function with a @cmd tag:
# @cmd Build the project
build() {
cargo build
}Since recipes are ordinary Bash functions, manage dependencies by calling other recipes or helper functions in order. With set -e (the default in generated scripts), a failing step stops the recipe.
# @cmd
current() {
before
echo current
after
}
before() {
echo before
}
after() {
echo after
}$ argc current
before
current
after
Functions without @cmd are not exposed as commands, which makes it easy to keep helper functions private.
Related recipes can share a prefix and a separator:
# @cmd
test:unit() { :; }
# @cmd
test:bin() { :; }argc test:unit
argc test:binThe same convention works with . or @, for example test.unit and test@unit. These are single command names with readable prefixes; use :: instead when you need real nested commands (see @cmd).
Run argc without a subcommand to display the available recipes. If the root command has a main function or a default subcommand, that command runs instead (see below).
$ argc
Usage: Argcfile.sh <COMMAND>
Commands:
build
test
There are two ways to run a recipe by default.
# @cmd
build() { :; }
# @cmd
test() { :; }
main() {
build
}main runs when no subcommand is selected.
# @cmd
# @meta default-subcommand
build() { :; }
# @cmd
test() { :; }The marked recipe runs when no subcommand is selected and appears as [default] in help.
# @cmd
# @alias t
test() {
echo test
}argc tLike command names in a regular argc script, recipe names containing _ also get a hyphenated alias automatically.
Recipes access positional arguments through the normal Bash variables:
# @cmd
build() {
echo "$1"
echo "$@"
echo "$*"
}argc build foo barargc also exposes the same values through argc_* variables when the arguments are declared with @arg:
# @cmd
# @arg target!
build() {
echo "$argc_target"
}Declare them above the recipe and read the generated variables:
# @cmd A simple command
# @flag -f --flag A flag parameter
# @option --option <VALUE> An option parameter
# @arg arg A positional parameter
cmd() {
echo "flag: $argc_flag"
echo "option: $argc_option"
echo "arg: $argc_arg"
}$ argc cmd -h
A simple command
Usage: Argcfile.sh cmd [OPTIONS] [ARG]
Args:
[ARG] A positional parameter
Options:
-f, --flag A flag parameter
--option <VALUE> An option parameter
-h, --help Print help
$ argc cmd -f --option foo README.md
flag: 1
option: foo
arg: README.md
argc recognizes two optional hooks:
| Hook | When it runs |
|---|---|
_argc_before |
Before the selected command function, after variables are initialized |
_argc_after |
After the selected command function |
_argc_before() {
echo "before"
}
_argc_after() {
echo "after"
}
# @cmd
build() {
echo "build"
}argc buildbefore
build
after
Hooks also run for the root command and for nested subcommands. They are useful for setup, cleanup, timing, and logging.
Use @meta dotenv to load a .env file:
# @meta dotenv # loads .env
# @meta dotenv .env.local # or load .env.localUse @env to document and validate environment variables:
# @env FOO A normal variable
# @env BAR! A required variable
# @env MODE[dev|prod] A variable with possible valuesargc -hEnvironments:
FOO A normal variable
BAR* A required variable
MODE A variable with possible values [possible values: dev, prod]
If a required variable is missing, argc reports an error. If a variable has choices, argc validates the value. Root-level @env declarations are inherited by subcommands automatically.
Use @meta require-tools to check that commands are available before running a recipe:
# @meta require-tools awk sed
# @cmd
# @meta require-tools git
require-git() { :; }argc require-git
# error: missing tools: gitThe check runs before the recipe. A root-level declaration applies to the whole script; a command-level declaration applies to that command.
When argc finds an Argcfile.sh in a parent directory, it changes the working directory to the directory containing the Argcfile:
project/
├── Argcfile.sh
└── src/
# @cmd
build() {
echo "$PWD"
echo "$ARGC_PWD"
}$ cd /tmp/project/src
$ argc build
/tmp/project
/tmp/project/src
PWDpoints to the project root (the Argcfile directory).ARGC_PWDpoints to the directory whereargcwas invoked.
This makes recipes independent of the caller's current directory.