0x192/universal-android-debloater
Cross-platform GUI written in Rust using ADB to debloat non-rooted android devices. Improve your privacy, the security and battery life of your device.
Stale — last commit 2y ago
weakest axiscopyleft license (GPL-3.0) — review compatibility; last commit was 2y ago…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓28+ active contributors
- ✓GPL-3.0 licensed
- ✓CI configured
Show all 7 evidence items →Show less
- ⚠Stale — last commit 2y ago
- ⚠Concentrated ownership — top contributor handles 52% of recent commits
- ⚠GPL-3.0 is copyleft — check downstream compatibility
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/0x192/universal-android-debloater)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/0x192/universal-android-debloater on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: 0x192/universal-android-debloater
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/0x192/universal-android-debloater shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 2y ago
- 28+ active contributors
- GPL-3.0 licensed
- CI configured
- ⚠ Stale — last commit 2y ago
- ⚠ Concentrated ownership — top contributor handles 52% of recent commits
- ⚠ GPL-3.0 is copyleft — check downstream compatibility
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live 0x192/universal-android-debloater
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/0x192/universal-android-debloater.
What it runs against: a local clone of 0x192/universal-android-debloater — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in 0x192/universal-android-debloater | Confirms the artifact applies here, not a fork |
| 2 | License is still GPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 673 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of 0x192/universal-android-debloater. If you don't
# have one yet, run these first:
#
# git clone https://github.com/0x192/universal-android-debloater.git
# cd universal-android-debloater
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of 0x192/universal-android-debloater and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "0x192/universal-android-debloater(\\.git)?\\b" \\
&& ok "origin remote is 0x192/universal-android-debloater" \\
|| miss "origin remote is not 0x192/universal-android-debloater (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is GPL-3.0" \\
|| miss "license drift — was GPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "src/main.rs" \\
&& ok "src/main.rs" \\
|| miss "missing critical file: src/main.rs"
test -f "src/core/sync.rs" \\
&& ok "src/core/sync.rs" \\
|| miss "missing critical file: src/core/sync.rs"
test -f "src/core/uad_lists.rs" \\
&& ok "src/core/uad_lists.rs" \\
|| miss "missing critical file: src/core/uad_lists.rs"
test -f "src/gui/mod.rs" \\
&& ok "src/gui/mod.rs" \\
|| miss "missing critical file: src/gui/mod.rs"
test -f "Cargo.toml" \\
&& ok "Cargo.toml" \\
|| miss "missing critical file: Cargo.toml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 673 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~643d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/0x192/universal-android-debloater"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Universal Android Debloater GUI is a cross-platform Rust application that communicates via ADB (Android Debug Bridge) to safely disable or uninstall system bloatware and unnecessary packages on non-rooted Android devices without risk of bricking. It provides curated debloat lists (GFAM, AOSP, OEM manufacturers, carriers) with detailed package documentation to improve privacy, security, and battery life while maintaining device bootability. Modular monolith: src/core/ contains business logic (ADB sync in sync.rs, config in config.rs, UAD lists in uad_lists.rs), src/gui/ contains the Iced-based UI layer (views/ for pages like list.rs and settings.rs, widgets/ for components like package_row.rs and modal.rs), and resources/ contains static assets (icons.json, icons.ttf, uad_lists.json). Main entry point is src/main.rs.
👥Who it's for
Android power users and privacy-conscious individuals who want to remove pre-installed bloatware without rooting their devices, and developers contributing to the open-source debloater community who need a GUI tool with multi-device support and package documentation.
🌱Maturity & risk
Early-stage but actively maintained: v0.5.1 is current, the project is a ground-up Rust rewrite of the original UAD project, has GitHub Actions CI/CD (build_artifacts.yml, ci.yml, release.yml), and maintains a CHANGELOG and detailed issue templates. However, the README explicitly states 'still in an early stage of development,' suggesting active but pre-1.0 status with ongoing feature development.
Moderate risk: the codebase is Rust (memory-safe) but interacts with a critical system tool (ADB) that can permanently modify devices if misused—the README emphasizes backup and factory reset recovery. Dependencies include iced (GUI framework from GitHub HEAD, not pinned), and the single-maintainer structure (w1nst0n) creates maintenance risk. The optional self-update feature (flate2, tar) adds supply-chain surface if enabled.
Active areas of work
Based on the file structure, active development targets: package documentation (update-apps-description-or-recommendation.md issue template suggests ongoing curation), multi-device/multi-user support features, and UI refinement through the views and widgets modules. The release.yml and build_artifacts.yml suggest active CI/CD pipeline maintenance. Version 0.5.1 suggests recent patch work.
🚀Get running
Clone and build with Cargo: git clone https://github.com/0x192/universal-android-debloater.git && cd universal-android-debloater && cargo build --release (uses default 'wgpu' feature for GPU-accelerated rendering). For development: cargo build for debug builds with faster compilation.
Daily commands:
cargo run --release starts the GUI application. Development build: cargo run (slower compilation, debug symbols). The app requires ADB to be installed and an Android device with USB Debugging enabled connected to the host.
🗺️Map of the codebase
src/main.rs— Application entry point and main event loop; all contributors must understand how the GUI is initialized and message routing workssrc/core/sync.rs— Core ADB synchronization and device communication logic; critical for all debloat operations and device state managementsrc/core/uad_lists.rs— Loads and manages the package database from resources/assets/uad_lists.json; essential for understanding what packages are available for removalsrc/gui/mod.rs— GUI state machine and view orchestration using Iced; every UI change routes through hereCargo.toml— Project manifest with Iced framework dependency and feature flags; contributors need to understand the wgpu/glow/self-update tradeoffssrc/core/config.rs— User configuration persistence and settings management; affects behavior across all subsystemsresources/assets/uad_lists.json— Package database with descriptions and safety recommendations; core data asset for the entire application
🧩Components & responsibilities
- ADB Sync (src/core/sync.rs) (std::process::Command, tokio async, regex parsing) — Manages ADB process spawning, device enumeration, package querying, and uninstall operations
- Failure mode: If ADB is not installed/in PATH, device not connected via USB with debugging enabled, or malformed ADB output, package queries fail silently or panic
- GUI State Machine (src/gui/mod.rs) (Iced, iced_native, Message enum) — Iced-based message dispatcher; maintains View enum state and delegates to view-specific update functions
- Failure mode: Unhandled Message variants cause panics; improper state transitions can leave UI in inconsistent state
- Package Database (src/core/uad_lists.rs) (serde_json, regex) — Loads JSON and provides package metadata lookup; matches device packages against known safe/unsafe/exotic lists
- Failure mode: Corrupted uad_lists.json prevents startup
🛠️How to make changes
Add a new view/tab to the UI
- Create a new view module in src/gui/views/your_view.rs with a view function returning iced::Element (
src/gui/views/your_view.rs) - Add the module declaration to src/gui/views/mod.rs (
src/gui/views/mod.rs) - Add a new variant to the Views enum in src/gui/mod.rs (
src/gui/mod.rs) - Handle the new view state in the update() method and add navigation button in src/gui/widgets/navigation_menu.rs (
src/gui/widgets/navigation_menu.rs)
Add a new package category or safety level to the database
- Define new enum variants in src/core/uad_lists.rs for the category/safety level (
src/core/uad_lists.rs) - Add entries to resources/assets/uad_lists.json with the new category/safety field (
resources/assets/uad_lists.json) - Update filtering logic in src/gui/views/list.rs to handle the new category (
src/gui/views/list.rs)
Add a new configuration option
- Add a new field to the Config struct in src/core/config.rs with serde derive (
src/core/config.rs) - Add UI control in src/gui/views/settings.rs to allow user to set the option (
src/gui/views/settings.rs) - Handle the setting in src/gui/mod.rs Message enum and update() method (
src/gui/mod.rs) - Persist the setting in src/core/save.rs if needed (
src/core/save.rs)
🔧Why these technologies
- Rust — Memory safety without garbage collection; enables cross-platform compilation for Windows, macOS, Linux; critical for ADB-based tool reliability
- Iced GUI framework — Elm-inspired architecture with message-driven state management; enables robust UI without mutable state; supports both wgpu and OpenGL rendering
- ADB (Android Debug Bridge) — Only viable way to interact with non-rooted Android devices; allows package queries and uninstalls without root via adb shell pm commands
- JSON assets (uad_lists.json) — Decouples package metadata from code; allows community updates to package safety information without recompilation
⚖️Trade-offs already made
-
No-root operation only
- Why: Root access is risky and device-specific; ADB without root is universally available on modern Android
- Consequence: Limited to uninstalling user-installed and some system packages via pm uninstall; cannot fully remove all system packages that rooted tools can remove
-
Shipped JSON database vs. online sync
- Why: Works offline; no external dependencies at runtime; faster startup
- Consequence: Package database is static until new release; community contributions require PR to update uad_lists.json
-
Single-threaded Iced event loop with async blocks
- Why: Simplicity; Iced's architecture handles concurrency internally; prevents UI freezing
- Consequence: ADB operations must use tokio async; blocking operations can still stall if not properly awaited
-
Feature-gated self-update with flate2+tar
- Why: Optional to reduce binary size and dependencies for distributions that provide updates
- Consequence: Users must handle updates manually if compiled with no-self-update feature
🚫Non-goals (don't propose these)
- Does not support rooted devices or Magisk-based modifications
- Does not handle ADB connection setup or USB driver installation (assumes ADB is pre-configured)
- Not a real-time backup/restore tool; only tracks what was removed
- Does not provide custom ROM flashing or bootloader manipulation
- Does not attempt recovery of bricked devices (relies on user factory reset)
🪤Traps & gotchas
ADB must be in PATH or discoverable by the system—no bundled ADB fallback visible. The iced dependency is pinned to GitHub HEAD (not a release version), which can introduce breaking changes; check Cargo.lock for exact commit. Multi-device support requires manual device selection in the GUI—no auto-detection fallback if multiple devices are attached. The uad_lists.json must be manually updated; there's no auto-sync mechanism for new packages discovered in the Android ecosystem. Optional self-update feature (enabled by default, disabled with --no-default-features) downloads and extracts binaries—verify network/HTTPS setup in production.
🏗️Architecture
💡Concepts to learn
- Android Debug Bridge (ADB) — Core transport layer for all debloater operations; understanding adb shell pm commands (package manager) is essential to reading src/core/sync.rs
- Elm Architecture (Model-View-Update) — Iced framework uses this functional reactive pattern; the GUI state machine in src/gui/mod.rs follows MVU, making message routing and event handling non-obvious to imperative developers
- Package Manager (pm) commands — The 'pm disable' vs 'pm uninstall' distinction is critical—disabling is reversible on non-rooted devices (covered in FAQ), while uninstall requires root; this semantic is hardcoded in sync.rs operations
- Multi-user Android profiles — Debloater must track packages across work profiles and guest accounts separately; sync.rs queries and disables packages per user ID, complicating device state tracking
- Attack surface reduction — Philosophical goal of the project (mentioned in README)—each package removal reduces exploitable code; understanding CVE risk categories helps prioritize which lists (GFAM vs OEM) users should apply
- Export/Import serialization patterns — User selections are serialized to uad_exported_selection.txt (plain text format, read in save.rs); this enables migration between devices but requires careful validation of package IDs to avoid misapplied debloating
- Device bootloop recovery — README warns that removing essential boot packages causes bootloops, but recovery is guaranteed after 5 failed boots (auto-recovery mode); this safety guarantee is the core differentiation from rooted debloaters and must be preserved in all package descriptions
🔗Related repos
0x192/universal-android-debloater— This is the same repo's reference—listed for completeness as the Rust rewrite of the original UAD projectW1nst0n/universal-android-debloater— The original UAD project (predecessor) written in Python; users may reference it for historical debloat lists or migration guidesadb-sync/adb-sync— Complementary tool for bidirectional file syncing via ADB; users of this debloater often need to backup/restore app data before removing packagesiced-rs/iced— The upstream GUI framework dependency; contributors working on UI must understand Iced's elm-like architecture and Message/View patternsNvChad/NvChad— Not directly related, but common in Rust tooling ecosystems—some users extend UAD with custom configuration via Vim integrations for batch debloat operations
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for src/core/utils.rs and src/core/uad_lists.rs
The core utility and list parsing logic lacks test coverage. Given that uad_lists.rs parses the critical resources/assets/uad_lists.json and utils.rs likely contains package filtering/validation logic, comprehensive unit tests would catch regressions early and document expected behavior. This is especially important for a debloater where incorrect parsing could lead to users accidentally removing critical system packages.
- [ ] Create src/core/utils_tests.rs with tests for regex patterns, string parsing, and file path operations
- [ ] Create src/core/uad_lists_tests.rs with tests for JSON deserialization, schema validation, and package categorization
- [ ] Update .github/workflows/ci.yml to run
cargo testin the test job (currently missing explicit test execution) - [ ] Document test patterns in CONTRIBUTING.md for future contributors
Implement integration tests for ADB communication in src/core/sync.rs
The sync.rs module handles the critical ADB device communication, but there's no evidence of integration tests. Adding integration tests (using mocked ADB responses or test fixtures) would verify command construction, response parsing, and error handling without requiring a real Android device. This prevents subtle bugs in device communication that could corrupt user data.
- [ ] Create tests/adb_integration_tests.rs with mock ADB command builders and response parsers
- [ ] Add test fixtures in tests/fixtures/adb_responses.json for various ADB output formats
- [ ] Test edge cases: device disconnection, permission errors, malformed responses from src/core/sync.rs
- [ ] Update GitHub Actions ci.yml to run integration tests with
cargo test --test '*'
Add E2E UI tests for critical user flows in src/gui/views/list.rs and src/gui/views/settings.rs
The GUI is the primary user interface for this safety-critical tool, but there are no automated UI tests visible in the CI pipeline. Adding end-to-end tests would catch regressions in package selection workflows, settings persistence, and theme application. Since this uses the Iced framework, tests can verify state transitions without requiring manual testing.
- [ ] Set up Iced testing utilities or screenshot/state comparison in tests/ directory
- [ ] Write tests for list.rs: package filtering, selection state, uninstall confirmation flows
- [ ] Write tests for settings.rs: settings load/save, theme switching, ADB connection validation
- [ ] Add UI test job to .github/workflows/ci.yml that runs headless (using xvfb on Linux)
🌿Good first issues
- Add test coverage for src/core/sync.rs ADB command parsing—currently no visible unit tests for debloater operations (uninstall, disable, restore mocking)
- Extend src/gui/widgets/modal.rs with a confirmation dialog for destructive operations (uninstall); the README warns about bootloops but no pre-action warning modal is visible in the widget set
- Document package categories in resources/assets/uad_lists.json with inline schema comments or generate a SCHEMA.md file—new contributors cannot distinguish why a package belongs to 'GFAM' vs 'Manufacturer' without reading code
⭐Top contributors
Click to expand
Top contributors
- @0x192 — 52 commits
- @AnonymousWP — 21 commits
- @nozwock — 2 commits
- @mmrabbani — 1 commits
- @uwuclxdy — 1 commits
📝Recent commits
Click to expand
Recent commits
11f27c6— fix: action button error whenmulti_user_modeis disabled (0x192)4ef967e— chore: uploadicomoon.ioproject file for UAD (0x192)1ef9522— pkg: addcom.google.android.apps.safetyhubAdded(#484) (mmrabbani)05a1625— pkg: add 71 Samsung WearOS packages (#481) (uwuclxdy)fd75b23— refactor: use more idiomatic expressions / DRY (#690) (lavafroth)3699d15— pkg: add and update some ColorOS apps (#475) (gs1719)7fbec57— fix: missing conditional compilation flag (0x192)68092ff— refactor: apply extra clippy lints suggestions (#673) (amaanq)69235a9— chore: update dependencies (0x192)588e310— fix: wrong recap counter (0x192)
🔒Security observations
- High · Unconstrained Dependency Version for ureq —
Cargo.toml - ureq dependency. The ureq dependency is specified with an unconstrained wildcard version ('*'), which means any version of ureq (including vulnerable ones) could be pulled during build. This creates a supply chain risk where a compromised or vulnerable version of ureq could be inadvertently included. Fix: Specify a constrained version range for ureq, e.g., 'ureq = { version = "^2.9.0", features = ["json"] }' to ensure deterministic builds and allow only patch-level updates. - High · Git Dependency Without Version Pinning —
Cargo.toml - iced and iced_native dependencies. The iced and iced_native dependencies are sourced directly from git without specifying a commit hash or tag. This means every build could pull different code, introducing non-determinism and potential supply chain attacks. The HEAD of the repository could contain malicious or broken code. Fix: Pin dependencies to specific commits: 'iced = { git = "https://github.com/iced-rs/iced.git", rev = "COMMIT_HASH" }' or use released versions instead. - Medium · Unconstrained toml Dependency Version —
Cargo.toml - toml dependency. The toml dependency is specified with an unconstrained version ('^0'), which permits breaking changes in 0.x releases. While less risky than wildcard, this still allows potentially incompatible versions. Fix: Specify an explicit version constraint, e.g., 'toml = "^0.5.11"' to ensure compatibility and security consistency. - Medium · Optional Self-Update Feature Without Cryptographic Verification —
Cargo.toml - self-update feature, src/core/update.rs. The application includes a self-update feature (using flate2 and tar) enabled by default. Without explicit evidence of cryptographic signature verification in the codebase structure, this could allow man-in-the-middle attacks to inject malicious updates. Fix: Implement cryptographic signature verification (e.g., ECDSA or RSA) for all downloaded updates before extraction and execution. Verify against a pinned public key. - Medium · Insecure HTTP Transport Risk (ureq) —
Cargo.toml - ureq dependency, src/core/update.rs, src/core/uad_lists.rs. The ureq library is used for HTTP requests. Without explicit evidence of HTTPS enforcement throughout the codebase, there could be unencrypted communication with update servers or remote resources (e.g., uad_lists.json loading). Fix: Enforce HTTPS-only connections for all remote requests. Implement certificate pinning for critical endpoints (update servers, list repositories). Validate all TLS certificates properly. - Medium · No Evidence of Input Validation on ADB Commands —
src/core/sync.rs (inferred). The application interfaces with Android Debug Bridge (ADB) to remove packages. Without visible input validation in the file structure, there's a risk of command injection if package names or device IDs are not properly sanitized before being passed to ADB. Fix: Implement strict input validation and sanitization for all package names and device identifiers before constructing ADB commands. Use safe command execution APIs that prevent shell injection (e.g., exec-style APIs instead of shell-style). - Low · Release Binary Stripping May Reduce Debug Capability —
Cargo.toml - [profile.release] section. The release profile uses 'strip = "symbols"', which removes debugging symbols. While this reduces binary size, it can complicate security incident response and vulnerability analysis. Fix: Consider maintaining a separate release build with symbols available for security researchers and incident response teams. Document the trade-off between size and debuggability. - Low · No Evidence of Dependency Auditing —
.github/workflows/ci.yml. No 'cargo-audit' configuration or security scanning workflow is evident in the CI/CD pipeline files shown (would expect checks in .github/workflows/ci.yml). Fix: Integrate 'cargo-audit' into the
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.