# How to Use CLI Arguments for Boot Tasks and Configuration in Sniffnet

> Learn to use CLI arguments for boot tasks and configuration in Sniffnet. Explore how clap handles arguments for pre-configuring the GUI before launch.

- Repository: [Giuliano Bellini/sniffnet](https://github.com/GyulyVGC/sniffnet)
- Tags: how-to-guide
- Published: 2026-04-28

---

**Sniffnet uses the clap crate to parse CLI arguments in [`src/cli/mod.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/cli/mod.rs), executing immediate side effects via `Args::handle()` and constructing an Iced boot task chain via `Args::get_boot_task_chain()` to pre-configure the GUI before it launches.**

Sniffnet is an open-source network monitoring tool written in Rust that exposes a command-line interface for controlling startup behavior and configuration management. By using CLI arguments for boot tasks and configuration in Sniffnet, you can automate packet capture initialization, inspect configuration paths, and reset user settings without navigating the graphical interface.

## CLI Structure and Argument Definitions

The command-line interface is defined in [`src/cli/mod.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/cli/mod.rs) using the **clap** crate's derive API. The `Args` struct, located at lines 9-16, declares all available options with `#[derive(Parser)]` and `#[command(...)]` attributes that expose the program name, version from [`src/utils/formatted_strings.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/utils/formatted_strings.rs), and application description.

Key command-line options include:

- **`-a, --adapter <NAME>`**: Specifies a network adapter to begin sniffing immediately. When omitted, Sniffnet defaults to the device configured in the global `CONF` object from [`src/gui/types/conf.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/types/conf.rs).
- **`-c, --config-path`**: Prints the absolute path to the configuration file and terminates the process.
- **`-r, --restore-default`**: Resets all user settings to the defaults defined in `Conf::default()` and exits.
- **`-l, --logs`**: (Windows only) Opens the latest log file in Explorer. When this flag is absent on Windows, the log file is truncated before startup.

## Handling Immediate Side Effects

Before the GUI initializes, the `Args::handle()` method (lines 34-76 in [`src/cli/mod.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/cli/mod.rs)) parses the command line and executes side-effect operations. This synchronous handler checks for utility flags and performs the requested action immediately.

Each branch prints a formatted message to stdout and terminates the process with an appropriate exit code. For example, invoking `--restore-default` invokes the reset logic and exits with code `0`, ensuring the graphical application never starts when these configuration flags are present. This architecture guarantees that `--config-path` and `--restore-default` complete as discrete maintenance tasks without window initialization overhead.

## Building the Boot Task Chain

When launching normally without utility flags, `Args::get_boot_task_chain()` constructs an **iced** `Task<Message>` that drives the first events of the GUI. This method, implemented at lines 81-90 in [`src/cli/mod.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/cli/mod.rs), chains together declarative messages that execute after the window appears.

The boot sequence starts with `window::latest().map(Message::StartApp)` to obtain the most recent window handle. If the `--adapter` argument was provided, the method extends the chain with three consecutive messages:

1. `Message::SetCaptureSource(CaptureSourcePicklist::Device)` – configures the UI to use a device-based capture source.
2. `Message::DeviceSelection(adapter)` – injects the user-specified adapter name into the application state.
3. `Message::Start` – triggers immediate packet capture without requiring manual interaction.

This declarative approach separates CLI configuration from GUI implementation, allowing the command line to pre-configure the application state before the first frame renders.

## Entry Point Integration

In [`src/main.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/main.rs) (lines 57-60), the application entry point orchestrates the CLI and GUI initialization. The code first invokes `Args::handle()` to process any immediate side effects. Then, it stores the parsed `Args` instance and passes `args.get_boot_task_chain()` to the Iced `application` function as the **initial task**.

This integration ensures that CLI-driven configuration—particularly adapter selection via `--adapter`—is applied atomically when the window appears. The boot task chain runs automatically as part of the Iced runtime initialization, bridging the gap between command-line parameters and reactive UI state.

## Practical Usage Examples

Start Sniffnet and immediately begin capturing from interface `eth0`:

```bash
sniffnet --adapter eth0

```

Display the absolute path to the configuration file for manual editing:

```bash
sniffnet --config-path

```

Reset all user settings to built-in defaults:

```bash
sniffnet --restore-default

```

On Windows, open the latest log file in Explorer:

```bash
sniffnet --logs

```

## Summary

- Sniffnet's CLI is implemented in [`src/cli/mod.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/cli/mod.rs) using the **clap** crate with a derive-based `Args` struct defined at lines 9-16.
- **Immediate side effects** (config path display, default restoration, log viewing) are handled synchronously by `Args::handle()` before the GUI launches.
- The **boot task chain** constructed by `Args::get_boot_task_chain()` creates an Iced task that automates GUI initialization, including optional automatic capture start via `--adapter`.
- Integration in [`src/main.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/main.rs) passes the boot task as the initial task to the Iced application, ensuring CLI arguments control the startup sequence.
- Configuration defaults are sourced from `Conf::default()` in [`src/gui/types/conf.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/types/conf.rs).

## Frequently Asked Questions

### How do I start Sniffnet capturing from a specific network interface immediately?

Use the `--adapter` flag followed by the interface name. This constructs a boot task chain in [`src/cli/mod.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/cli/mod.rs) that sequentially dispatches `Message::SetCaptureSource`, `Message::DeviceSelection`, and `Message::Start` to automate capture initialization without manual GUI interaction.

### What happens when I run Sniffnet with --restore-default?

The `Args::handle()` method detects the `--restore-default` flag and immediately resets all user settings to `Conf::default()` values defined in [`src/gui/types/conf.rs`](https://github.com/GyulyVGC/sniffnet/blob/main/src/gui/types/conf.rs). It prints a confirmation message and exits with code `0`, terminating before the GUI window appears.

### Where is the Sniffnet configuration file stored?

Run `sniffnet --config-path` to display the absolute path. This utility flag triggers an immediate side effect in `Args::handle()` that prints the configuration directory location and exits, allowing you to locate the file for backup or manual editing without launching the application.

### Why does Sniffnet exit immediately after using --config-path or --restore-default?

These flags are designed as **maintenance utilities** rather than runtime options. The `Args::handle()` method intentionally terminates the process after completing the requested side effect to prevent unnecessary GUI initialization, ensuring fast execution of configuration management tasks.