Where to Find the Main CLI Runner in the Aqua Project

The main CLI runner in the Aqua project is located at cmd/aqua/main.go, which initializes the application using the urfave-cli v3 framework and delegates execution to the command tree defined in pkg/cli/run.go.

The Aqua project is a declarative CLI version manager written in Go. Understanding where the main CLI runner resides is essential for contributors looking to extend functionality or debug execution flow. This guide pinpoints the entry point and explains how control flows from the binary initialization to the individual command handlers.

Locating the Main CLI Runner Entry Point

The absolute entry point for the Aqua binary is cmd/aqua/main.go. This file contains the main() function that the Go runtime executes when the aqua command is invoked.

// File: cmd/aqua/main.go
package main

import (
    "github.com/aquaproj/aqua/v2/pkg/cli"
    "github.com/suzuki-shunsuke/urfave-cli-v3-util/urfave"
)

func main() {
    // "aqua" is the command name, version is injected at build time,
    // and cli.Run holds the full command tree.
    urfave.Main("aqua", version, cli.Run)
}

This design keeps the main package minimal, containing only the necessary imports and a single function call to bootstrap the CLI framework.

How the Main CLI Runner Delegates to the Command Tree

After the main() function executes, control passes to urfave.Main, a utility wrapper around the urfave-cli v3 library. This wrapper handles flag parsing, help generation, and command routing.

The third argument, cli.Run, is the critical bridge to Aqua's business logic. Defined in pkg/cli/run.go, this function constructs the root command and registers all sub-commands such as install, update, exec, and which.

When a user runs aqua install, the execution flow follows this path:

  1. cmd/aqua/main.gomain()
  2. urfave.Main() parses global flags and identifies the sub-command
  3. cli.Run() routes to the specific command handler in pkg/cli/commands/
  4. The command implementation executes the tool installation logic

Exploring the CLI Package Structure

The pkg/cli directory contains the modular architecture that supports the main CLI runner. Understanding these files helps trace how commands are registered and executed.

Key Files in the CLI Package:

  • pkg/cli/run.go – Contains the Run function that instantiates the root command and attaches all sub-commands using the urfave-cli API.
  • pkg/cli/commands/*.go – Individual command implementations. Each file typically exports a function that returns a *cli.Command struct defining flags, arguments, and the action function.
  • pkg/cli/flags.go – Defines shared flag variables and parsing logic used across multiple commands to ensure consistent behavior for options like --config or --log-level.

This separation of concerns allows the main runner to remain agnostic of specific command details while providing a clean extension point for new functionality.

Running the Aqua CLI Locally

To verify the main CLI runner behavior or test modifications, you can build and execute the binary from source.

Build the binary:


# Clone the repository

git clone https://github.com/aquaproj/aqua.git
cd aqua

# Build the main CLI runner

go build -o aqua ./cmd/aqua

Execute commands:


# Show version information (injected at build time)

./aqua version

# Install tools defined in aqua.yaml

./aqua install

# Execute a managed tool

./aqua exec -- go version

# Locate the installation path of a specific tool

./aqua which golangci-lint

For programmatic integration, you can embed Aqua's CLI within another Go application by importing the pkg/cli package and invoking the Run function directly with custom arguments.

Summary

  • The main CLI runner entry point is located at cmd/aqua/main.go, containing the main() function that bootstraps the application.
  • Execution delegates immediately to urfave.Main, which wraps the urfave-cli v3 framework for flag parsing and command routing.
  • The cli.Run function in pkg/cli/run.go constructs the command tree and registers all sub-commands like install, exec, and which.
  • Individual command implementations reside in pkg/cli/commands/, with shared flags defined in pkg/cli/flags.go.
  • This architecture separates binary initialization from business logic, enabling easy testing and extension of the Aqua CLI.

Frequently Asked Questions

Where is the main function located in the Aqua project?

The main function is located in cmd/aqua/main.go. This file serves as the entry point for the compiled binary, importing the CLI package and invoking the bootstrap utility to start the command-line interface.

How does Aqua handle command routing from the main entry point?

Aqua uses the urfave.Main wrapper from the urfave-cli-v3-util package to handle command routing. This utility parses command-line arguments, matches them against the command tree defined in pkg/cli/run.go, and dispatches execution to the appropriate handler in pkg/cli/commands/.

Can I extend Aqua by adding new sub-commands to the main CLI runner?

Yes, you can extend Aqua by adding new sub-commands. Create a new command implementation in pkg/cli/commands/ following the existing pattern, then register it in pkg/cli/run.go by adding it to the command slice passed to the root command constructor. The modular design keeps the main runner in cmd/aqua/main.go unchanged.

What is the difference between cmd/aqua/main.go and pkg/cli/run.go?

cmd/aqua/main.go is the binary entry point that initializes the application and imports the CLI framework. It contains only the main function and minimal bootstrap logic. pkg/cli/run.go contains the actual command tree construction, sub-command registration, and the Run function that defines how the CLI behaves. This separation allows the core logic to be tested independently of the binary entry point.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →