Skip to content

CLI Reference

ahoy [flags] [command] [args...]

Global flags belong before the command name. Everything after the command name belongs to that command - see Passing arguments to commands.

Flag Short Description
--file <path> -f Use a specific config file instead of searching for .ahoy.yml
--verbose -v Enable verbose output
--version Print the Ahoy version and exit
--help -h Show help
Terminal window
ahoy --verbose deploy # --verbose is Ahoy's
ahoy deploy --verbose # --verbose is passed to the deploy command

Management commands for your Ahoy configuration.

Downloads a starter .ahoy.yml into the current directory. Without a URL it fetches the official examples file (30+ ready-to-use commands). Pass a custom URL to download your own template.

Terminal window
ahoy config init # Download official examples
ahoy config init https://... # Download a custom template
ahoy config init --force # Overwrite an existing .ahoy.yml

Checks your .ahoy.yml (and any imported files) for common issues:

  • Unsupported or missing fields
  • Missing import files (not marked optional: true)
  • Features that require a newer version of Ahoy
Terminal window
ahoy config validate

Errors are always shown. Warnings are shown in verbose mode (--verbose). The validator also provides actionable suggestions when it finds a problem.

Terminal window
ahoy help # Root help listing
ahoy help <command> # Help for a specific command

ahoy init still works but is deprecated. It redirects to ahoy config init with a notice. Prefer ahoy config init in any new scripts or documentation.

confirm is not built in - it is a convention: a small command you define in your own config (and can import from confirmation.ahoy.yml) to guard destructive operations. Because Ahoy commands can call other Ahoy commands, it behaves like a reusable function.

It prompts with your message and exits 0 when the answer is y, or 1 otherwise, so it chains with &&, || and || exit 0:

Terminal window
ahoy confirm "Are you sure you want to do this?"
# >> Are you sure you want to do this? [y/N]
ahoy confirm "Delete the build directory?" && rm -rf ./build || echo "Skipping..."

A minimal definition:

commands:
confirm:
hide: true
cmd: |
read -r -p ">> $1 [y/N] " response
[ "$response" = "y" ]

hide: true keeps the helper out of the command listing without disabling it.

The examples file carries a fuller version that also works unattended, controlled by two environment variables you set yourself:

Variable Effect
AHOY_CONFIRM_RESPONSE Answers the prompt instead of reading from the terminal (e.g. y)
AHOY_CONFIRM_WAIT_SKIP Set to 1 to skip the 3-second grace pause in automated mode
Terminal window
AHOY_CONFIRM_RESPONSE=y AHOY_CONFIRM_WAIT_SKIP=1 ahoy db:reset

See Writing Commands for the full pattern.

Ahoy searches for .ahoy.yml in the following order:

  1. The file specified by --file / -f
  2. .ahoy.yml in the current directory
  3. .ahoy.yml in each parent directory, up to the filesystem root

The directory containing the found config file becomes the working directory for all commands.

Arguments after the command name are passed through as bash positional parameters:

Terminal window
ahoy greet World # $1 = "World"
ahoy copy a.txt b.txt # $1 = "a.txt", $2 = "b.txt"
ahoy run npm test # $@ = "npm test"

Everything after the command name is passed through verbatim and in order, including anything that looks like a flag. Ahoy never claims a flag there, even one of its own - which is what makes Ahoy usable as a wrapper around other tools:

Terminal window
ahoy test --filter=MyTest --stop-on-failure # all four tokens reach the command
ahoy fix-perms chown -R www-data:www-data . # -R is not Ahoy's to take
ahoy phpunit --help # PHPUnit's help, not Ahoy's

To reach Ahoy’s own help for a command, use ahoy help <command>.

A leading -- is accepted for readability and removed before the arguments are passed on. Any later -- is the command’s own data and reaches it untouched, which matters for the many tools that need a separator of their own:

Terminal window
ahoy run -- npm test # $@ = "npm test"
ahoy k exec mypod -- ls /app # $@ = "exec mypod -- ls /app"
ahoy git checkout -- src/main.go # $@ = "checkout -- src/main.go"
Typed Read by Reaches the command as
ahoy --verbose test Ahoy -
ahoy -f build.yml test Ahoy -
ahoy -f=build.yml test Ahoy -
ahoy test --verbose Command --verbose
ahoy test --filter=X Command --filter=X
ahoy test -R -p /tmp/logs Command -R -p /tmp/logs
ahoy test --help Command --help
ahoy test -- --anything Command --anything
ahoy test a -- b Command a -- b
ahoy help test Ahoy -

Ahoy passes stdin, stdout and stderr through unchanged - each command inherits the streams of the process that invoked Ahoy, whether those are a terminal, pipes, or files. It does not read, buffer, tee or copy them, so:

  • Interactive commands get a real prompt and readline support when stdin is attached to a TTY
  • Full-screen and TUI commands (gum, fzf, anything on Bubble Tea) can query the terminal size and draw correctly when the relevant streams are a TTY
  • Output appears as it is produced rather than when the command exits
  • Redirection behaves as it would without Ahoy - ahoy test 2>errors.log sends the command’s stderr to the file, unbuffered, while stdout stays on the terminal

Exit codes pass through unchanged - see Exit codes.

Terminal window
# Generate and install the completion script
mkdir -p ~/.bash_completion.d
ahoy --generate-bash-completion > ~/.bash_completion.d/ahoy
echo '. ~/.bash_completion.d/ahoy' >> ~/.bashrc
source ~/.bashrc

Use the dedicated plugin at ahoy-cli/zsh-ahoy. See the Shell Autocompletion guide for setup instructions.

Code Meaning
0 Success
1 General error (command failed, config not found, etc.)

Ahoy passes the exit code of the underlying command through unchanged.

Ahoy injects the following variables into every command’s environment:

Variable Value
AHOY_COMMAND_NAME The name of the command being run
AHOY_CMD Path to the ahoy binary

These are available to any script invoked through Ahoy.