# UAD GUI vs CLI: Differences and Shared Core Logic Explained

> Explore the Universal Android Debloater GUI vs CLI. Understand their differences and how they share core logic for efficient device management. Learn more now.

- Repository: [Universal-Debloater-Alliance/universal-android-debloater-next-generation](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation)
- Tags: deep-dive
- Published: 2026-06-20

---

**The Universal Android Debloater Next Generation provides both a graphical interface built with Iced and a terminal interface powered by clap, with both front-ends delegating all device communication and package management to a shared `uad-core` crate.**

The Universal Android Debloater Next Generation (UAD NG) is organized as a Rust workspace containing three distinct crates: `uad-gui`, `uad-cli`, and `uad-core`. While the GUI and CLI components present different user experiences, they rely on the exact same underlying logic for ADB communication, package filtering, and state management. This architecture ensures consistent behavior whether you prefer clicking through a modern interface or scripting terminal commands.

## GUI Component Architecture

The graphical interface (`uad-gui`) delivers a desktop application experience using the **Iced** UI library for Rust.

### Entry Point and Event Loop

The GUI initializes in [`crates/uad-gui/src/main.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/main.rs), which creates an Iced `Application` and enters the event loop. Unlike the CLI, the GUI runs on a single UI thread, delegating asynchronous work to `tokio` tasks inside Iced's `Command` system.

### Visual Components

Rich visual elements are defined across several modules:

- **`crates/uad-gui/src/widgets/`** – Contains reusable UI components like lists and package rows
- **[`crates/uad-gui/src/theme.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/theme.rs)** – Defines colors, fonts, and styling
- **`crates/uad-gui/src/views/`** – Implements screens such as the package list, settings dialog, and about page

When a user clicks the **Uninstall** button in the interface, the handler in [`crates/uad-gui/src/widgets/package_row.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/widgets/package_row.rs) triggers the core logic. The GUI renders tooltips, icons, and status indicators while background tasks execute device commands.

## CLI Component Architecture

The command-line interface (`uad-cli`) provides a text-based experience built with **clap** for argument parsing and **tokio** for async execution.

### Entry Point and Command Dispatch

[`crates/uad-cli/src/main.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-cli/src/main.rs) serves as the entry point, using `clap::Parser` to process arguments and dispatch to sub-commands via a `match cli.command` block. The CLI runs as a standard async binary with `#[tokio::main]`, spawning tasks as needed for concurrent operations.

### Command Structure

The CLI operates through explicit sub-commands:

- `list` – Display packages with filtering options
- `uninstall` – Remove specific packages
- `enable` / `disable` – Toggle package states
- `update` – Refresh the debloat list from GitHub

Implementation details for each command reside in [`crates/uad-cli/src/commands.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-cli/src/commands.rs), which provides thin wrappers around `uad-core` functionality. Output formatting is handled separately in [`crates/uad-cli/src/output.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-cli/src/output.rs), ensuring plain text suitable for piping and scripting.

### Interactive Mode

Beyond single commands, [`crates/uad-cli/src/repl.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-cli/src/repl.rs) implements an interactive REPL mode for users who prefer a shell-like experience within the terminal.

## How GUI and CLI Share Core Logic

Both front-ends are thin clients that delegate all substantive work to the **`uad-core`** crate. This shared library contains pure Rust modules with no UI assumptions, making it environment-agnostic.

### Core Functionality Map

| Feature | Implementation File | Used By |
|---------|---------------------|---------|
| **ADB Communication** | [`crates/uad-core/src/adb.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/adb.rs) | Both GUI and CLI |
| **Package List Management** | [`crates/uad-core/src/uad_lists.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/uad_lists.rs) | Both GUI and CLI |
| **State Changes** | [`crates/uad-core/src/save.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/save.rs) & [`src/sync.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/src/sync.rs) | Both GUI and CLI |
| **Configuration** | [`crates/uad-core/src/config.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/config.rs) | Both GUI and CLI |
| **Update Checking** | [`crates/uad-core/src/update.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/update.rs) | Both GUI and CLI |

### Typical Execution Flow

When you initiate a package removal, the execution path follows the same core logic regardless of interface:

1. **Action Initiation** – The GUI sends a message through the Iced application state, or the CLI parses the sub-command in [`main.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/main.rs)
2. **Core Delegation** – Both call `commands::change_package_state` (CLI) or the analogous core function (GUI)
3. **ADB Execution** – The core function interacts with [`adb.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/adb.rs) to execute `adb shell pm uninstall ...`
4. **Result Handling** – The GUI updates the widget state, while the CLI prints a status line via [`output.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/output.rs)

### Configuration Sharing

Both front-ends read from the same configuration files ([`config.toml`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/config.toml), [`uad_lists.json`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/uad_lists.json)) through `uad_core::config`. This ensures that settings like device preferences and list sources remain synchronized across usage modes.

## Practical Usage Examples

### CLI Package Listing

List removable packages on the first connected device using the terminal:

```bash
uad list --removal removable

```

The `list` sub-command in [`crates/uad-cli/src/commands.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-cli/src/commands.rs) parses these options and forwards them to `commands::list_packages`, which internally calls `uad_core::uad_lists` to retrieve and filter the package data.

### GUI Package Removal

Remove a package through the graphical interface:

1. Launch the application (`cargo run --bin uad-gui`)
2. Navigate to the *Packages* view, populated by `uad_core::uad_lists`
3. Select a package and click **Uninstall**
4. The widget handler in [`crates/uad-gui/src/widgets/package_row.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-gui/src/widgets/package_row.rs) calls `uad_core::save::uninstall_package`
5. The UI refreshes to show the package status as **Uninstalled**

Both workflows execute identical ADB commands through the shared core, ensuring consistent results.

## Summary

- **GUI (`uad-gui`)**: Built with Iced, provides visual package browsing with widgets and themed windows, running on a single UI thread with async task delegation
- **CLI (`uad-cli`)**: Built with clap and tokio, offers sub-command-based automation and REPL mode, outputting plain text for terminal use
- **Shared Core (`uad-core`)**: Houses all ADB communication in [`adb.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/adb.rs), package lists in [`uad_lists.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/uad_lists.rs), state changes in [`save.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/save.rs), and configuration in [`config.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/config.rs)
- **Consistency**: Both interfaces use identical logic for device operations, ensuring the same debloating behavior across graphical and terminal environments

## Frequently Asked Questions

### Can I use the GUI and CLI interchangeably on the same device?

Yes. Both front-ends interact with the same Android Debug Bridge (ADB) server and use identical logic from `uad_core`. You can configure packages using the GUI and later script operations using the CLI without conflicts, as both read from the same [`config.toml`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/config.toml) and [`uad_lists.json`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/uad_lists.json) files.

### Which component actually executes the ADB commands?

Neither the GUI nor CLI executes ADB commands directly. Both delegate to [`crates/uad-core/src/adb.rs`](https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/blob/main/crates/uad-core/src/adb.rs), which wraps the `adb` binary and handles device discovery, command execution, and error handling. This centralized approach ensures consistent command formatting and device communication across all interfaces.

### How do the GUI and CLI handle asynchronous operations differently?

The CLI uses `#[tokio::main]` with standard async task spawning throughout the command execution. The GUI runs on a single UI thread managed by Iced, using `tokio` tasks specifically within Iced's `Command` system to perform background work without blocking the interface. Both rely on the same `tokio` runtime but integrate it according to their respective framework requirements.

### Is it possible to add a web interface using the same core logic?

Yes. Because `uad-core` contains pure Rust modules with no UI dependencies, it can be imported into any environment. A web front-end could import `uad_core::adb`, `uad_core::uad_lists`, and `uad_core::save` to leverage the existing device communication and package management logic without duplicating code.