# How to Enable Verbose Logging in IPATool: Command Line and Code Examples

> Learn how to enable verbose logging in IPATool with command line flags and code examples. Improve debugging and troubleshooting for your IPA tool usage.

- Repository: [Majd/ipatool](https://github.com/majd/ipatool)
- Tags: how-to-guide
- Published: 2026-09-04

---

**Add the `--verbose` flag to any IPATool command to enable debug-level output, or set `Verbose: true` when programmatically creating a logger via `log.NewLogger()`.**

IPATool is a CLI utility for downloading and inspecting iOS app packages (IPA files) from the App Store. When troubleshooting download failures or analyzing API responses, you can enable **verbose logging** to expose detailed diagnostic information. This global setting switches the internal logger from **Info** to **Debug** level and is controlled through a persistent command-line flag and the `pkg/log` package.

## Root Command Flag Implementation (cmd/root.go)

The entry point for verbose mode begins in the root command definition. IPATool registers a persistent boolean flag `--verbose` that defaults to `false` and applies to all subcommands.

In [`cmd/root.go`](https://github.com/majd/ipatool/blob/main/cmd/root.go), the flag is bound to a package-level variable:

```go
cmd.PersistentFlags().BoolVar(&verbose, "verbose", false, "enables verbose logs")

```

Because this is a **persistent flag**, it is inherited by every subcommand (such as `download`, `search`, or `purchase`), allowing you to append `--verbose` to any operation without modifying individual command files.

## Logger Initialization Chain (cmd/common.go)

Once the flag is parsed, its value propagates through the dependency injection chain. The `newLogger` helper function in [`cmd/common.go`](https://github.com/majd/ipatool/blob/main/cmd/common.go) receives both the output format and the verbose boolean, forwarding them to the logging constructor:

```go
func newLogger(format string, verbose bool) log.Logger {
    return log.NewLogger(log.Args{
        Format:  format,
        Verbose: verbose,  // Passes the CLI flag value
    })
}

```

This centralized initialization ensures that all commands receive a consistently configured logger instance that respects the user's verbosity preference.

## Logger Internals (pkg/log/logger.go)

The core logging logic resides in [`pkg/log/logger.go`](https://github.com/majd/ipatool/blob/main/pkg/log/logger.go), where the `Logger` interface implementation handles the verbose state. The constructor stores the flag in a `verbose` field and selects the appropriate **zerolog** level:

- When `verbose` is `true`: the logger level is set to `Debug`
- When `verbose` is `false`: the logger level remains at `Info`

The struct exposes a `Verbose()` method that returns a `zerolog.Event` only when verbose mode is enabled, allowing the rest of the codebase to emit debug messages without conditional checks:

```go
func (l *logger) Verbose() *zerolog.Event {
    if l.verbose {
        return l.Logger.Debug()
    }
    return nil
}

```

Throughout IPATool's source, you will find calls like `logger.Verbose().Msg("authenticating with Apple")`. When verbose mode is off, these calls return `nil` and effectively become no-ops, preventing debug output from cluttering standard usage.

## Practical Usage Examples

### Command Line Usage

Append the global flag to any command to enable detailed output:

```bash

# Verbose download with debug logs

ipatool --verbose download com.example.app

# Verbose search

ipatool --verbose search "example app"

```

### Programmatic Usage in Go

If you are importing IPATool as a library or writing extensions, manually enable verbose mode by setting the `Verbose` field in the arguments struct:

```go
import (
    "os"
    "github.com/majd/ipatool/pkg/log"
)

func main() {
    logger := log.NewLogger(log.Args{
        Verbose: true,          // Enable debug level
        Writer:  os.Stdout,
    })
    
    // This emits a debug line only when verbose is true
    logger.Verbose().
        Str("bundle_id", "com.example.app").
        Msg("Starting download process")
}

```

### Inside Command Implementations

When working within the existing command framework, access the pre-configured logger through the dependencies container:

```go
// Inside a command implementation (e.g., cmd/download.go)
func runDownload(cmd *cobra.Command, args []string) error {
    // dependencies.Logger was created by newLogger(format, verbose)
    dependencies.Logger.Verbose().
        Str("app_id", args[0]).
        Msg("Resolving app metadata")
    
    // ... download logic continues
    return nil
}

```

## Summary

- **Flag Definition**: The `--verbose` flag is declared as a persistent boolean in [`cmd/root.go`](https://github.com/majd/ipatool/blob/main/cmd/root.go), making it available to all subcommands.
- **Propagation**: The flag value flows through [`cmd/common.go`](https://github.com/majd/ipatool/blob/main/cmd/common.go) via the `newLogger()` helper function.
- **Level Control**: [`pkg/log/logger.go`](https://github.com/majd/ipatool/blob/main/pkg/log/logger.go) interprets the flag to set the zerolog level to `Debug` when enabled, or `Info` by default.
- **Safe Usage**: The `Verbose()` method returns a proper event only when enabled, allowing debug logging statements to remain in production code without performance penalties.

## Frequently Asked Questions

### How do I enable verbose logging for a specific IPATool command?

Append the global `--verbose` flag to any command invocation. For example, `ipatool download com.example.app --verbose` or `ipatool --verbose search "app name"`. Because the flag is persistent and defined at the root command level, it can appear before or after the subcommand name.

### Does verbose logging affect all subcommands?

Yes. The flag is registered using `PersistentFlags()` in [`cmd/root.go`](https://github.com/majd/ipatool/blob/main/cmd/root.go), which means it is automatically inherited by every subcommand (download, search, purchase, etc.). You do not need to modify individual command files to support verbose output.

### Can I enable verbose mode programmatically when using IPATool as a library?

Yes. When constructing a logger via `log.NewLogger()`, set `Verbose: true` in the `log.Args` struct. This configuration overrides the CLI default and forces the logger to emit debug-level messages regardless of command-line flags.

### What logging library does IPATool use for verbose output?

IPATool uses **zerolog** for structured logging. The verbose mode works by returning `l.Logger.Debug()` from the `Verbose()` method when the flag is enabled, leveraging zerolog's level-based filtering to control output verbosity.