Introduction
You bought the TV. You didn't choose the ad slots on its home screen.
This is article 248 in the "One Open Source Project a Day" series. Today's project is CleanYourTV (Gathin23/cleanyourtv).
The author posted a before-and-after of their parents' TV, cleaned up by Claude Code over Wi-Fi. According to the README the tweet reached 7.4M views, people started doing the same to their own TVs, and their replies turned into the lists now in the repo. The project was created on 17 October 2026 and, at the time of writing, has nearly 38k stars and over 4,500 forks.
What makes it interesting isn't "yet another ad-removal script". It's the delivery model: the repo is a set of tools with safety rails, plus a prompt you hand to a coding assistant. The assistant discovers what is preinstalled on your particular TV and asks before touching anything you might use.
What You'll Learn
- What CleanYourTV does, and why "disable, don't uninstall" is its safety floor
- How the "back up → disable → install launcher" flow actually works
- How a 523 KB native launcher is designed, and how themes, module cards and add-ons extend it
- How it avoids leaving a TV with no home screen, and how to undo everything in one line
- How to detect and repair "drift" after a firmware update
- Scope and known limits
Prerequisites
- You know what ADB (Android Debug Bridge) is and are comfortable in a terminal
- A rough idea of what
pm disable-userdoes (explained below if not) - Interest in letting an AI coding assistant operate real hardware
Project Background
Overview
CleanYourTV targets Android TV and Google TV. These TVs often ship with vendor telemetry, ad services, content rows and a pile of preinstalled apps nobody asked for, and the home screen can carry sponsored content.
The idea is simple: Android TVs have the same debug bridge as Android phones. Switch on USB debugging in the TV's developer options, allow your computer once, and everything else is standard Android tooling.
No root, no cable, nothing uninstalled, and a one-line restore if you change your mind.
Author and Community
- Author: Gathin23 (GitHub user; project site cleanyour.tv)
- Created: 2026-10-17
- Former name: the repo was called tv-vibehack until 19 October; old links still work
- Community: per the README, 170+ TV lists from 200+ contributors within four days; the project card cites 316 TV models, 89 brands and 28 languages
The site also states that other domains using the name, such as cleanyourtv.com, are not run by this project.
Project Data
As of the GitHub page on 2026-10-26. These grow quickly, so treat them as a snapshot:
- ⭐ GitHub Stars: ~37,800
- 🍴 Forks: ~4,500
- 📦 Latest release: v3.0.0 (2026-10-25, after v2.4 through v2.7 shipped between 20 and 23 October)
- 📄 License: MIT (the Outfit typeface is under SIL OFL)
- 🌐 Website: cleanyour.tv
- 💻 Languages: Python, Java, Kotlin, Shell, PowerShell
Main Features
What It Does
Two things:
- Debloat: disable vendor telemetry, ad services, content rows and preinstalled junk
- Replace the home screen: install a very small native launcher as the default home, styled after Apple TV
The debloat half differs a lot by brand, so the project doesn't ship one universal list. It has the coding assistant discover what is on your TV and confirm item by item.
Use Cases
-
Cleaning your own TV
- Computer and TV on the same Wi-Fi; the assistant backs up, disables, installs and verifies with screenshots in about fifteen minutes
-
Only an Android phone, no laptop
- A community member, udhaykumarbala, built a free open-source phone app that connects to the TV, shows a plan first, saves a restore point, and then applies it
-
Helping family in another home
- Over a private Tailscale link, never by opening the ADB port on their router
-
Contributing your TV model
- One folder per model under
examples/, reusable by the next person with the same TV
- One folder per model under
-
Building on top
- SHOWCASE.md lists 121 derived projects: home screens, forks, add-ons, tools and ports to other platforms
Quick Start
You need a computer on the same Wi-Fi as the TV, and a coding assistant with shell access (Claude Code, Codex or Gemini CLI).
Step 1, on the TV: Settings → Device Preferences → About → press OK on Build seven times → back → Developer options → turn on USB debugging (and any Network/ADB debugging toggle). Keep the TV on.
Step 2, on your computer: clone the repo, open the folder in your assistant, then paste the contents of PROMPT.md and fill in your TV model.
git clone https://github.com/Gathin23/cleanyourtv
cd cleanyourtv
# open this folder in your coding assistant, paste PROMPT.md, fill in your TV modelStep 3, follow along: accept "Allow USB debugging?" on the TV, then answer the checklist: which apps you use, dock size, whether to keep the voice assistant, Chromecast and updates.
Cloning matters because the assistant reuses the repo's tools/disable.sh and launcher/build-and-install.sh instead of writing its own. The backup, the Home guard and the restore record all live in those scripts.
Doing It by Hand
Everything the assistant does, you can run yourself. The tools need only Python 3:
python3 -m venv tools/venv && tools/venv/bin/pip install -r tools/requirements.txt
export TV_HOST=192.168.1.50 # your TV's IP
tools/venv/bin/python -I tools/tv.py --probe # model, Android version, firmware
tools/disable.sh examples/xiaomi-mi-tv-4a/debloat.txt # apply a debloat list
tools/restore.sh examples/xiaomi-mi-tv-4a/debloat.txt # undo it, stock launcher back
TV_HOST=192.168.1.50 launcher/build-and-install.sh # build the launcher and make it Home
tools/theme.sh themes/aurora # push a theme; --reset removes itCore Features
-
Pitch-black home with a dock
- Four favourite apps in a rounded band, where Apple TV puts it
-
Top shelf and ambient glow
- The focused app's name in large type, with a glow taken from its artwork
-
One floating glass highlight
- Springs from tile to tile; the focused tile lifts and shows its name
-
Themes without a rebuild
- Colours, wallpaper, dock and columns pushed over Wi-Fi via
config.json; ten themes ship in the repo
- Colours, wallpaper, dock and columns pushed over Wi-Fi via
-
28 languages
- Follows the TV's language, with a fully mirrored right-to-left layout for Hebrew
-
Module cards
- Any TV app can declare its own tile, but each app needs your approval once before it appears
-
App library and tile menu
- Hold OK on a tile to Move, Remove from Home, or open App info
-
Clock screensaver
- A slowly drifting clock so nothing burns in
Advantages
| Aspect | CleanYourTV | Typing adb commands by hand | Flashing or rooting |
|---|---|---|---|
| Barrier | Assistant does the work; you answer questions | You must look up every package | High, and the method differs per brand |
| Reversibility | State recorded first, one-line restore | Depends on whether you wrote it down | May affect warranty, hard to roll back |
| Brand coverage | Community lists plus on-the-spot discovery | All on you | Varies by model |
| Home screen | Launcher included | None | Depends on what you flash |
Why look at it?
- It puts "AI operating real devices" inside a bounded toolset instead of letting the model improvise
- Everything goes through interfaces the TV exposes to its owner; no lock, DRM or copy protection is bypassed
- Community lists mean the next person with your model doesn't start from scratch
Deep Dive
How the Three Steps Work
The README summarizes the flow in one table:
| Step | What happens |
|---|---|
| Back up | The list of installed packages and settings |
| Disable | Vendor telemetry, ad services, content rows and preloaded junk, with pm disable-user |
| Install | A small native launcher, made the default home screen |
The key is step two. pm disable-user is the same switch as Settings → Apps → Disable. No app file is deleted; it's just turned off for the current user. That is where the project's reversibility comes from.
Protecting Home: Never Leave a TV Without One
The most dangerous failure in debloating is disabling the current home app before the new launcher is in place, so Home lands on a factory test app or the system crash-loops.
The scripts have several layers of defence:
- The install script asks the TV which launcher owns Home and only disables one it recognises, the four in
KNOWN_STOCK_LAUNCHERS:com.google.android.tvlauncher,com.google.android.apps.tv.launcherx,com.google.android.leanbacklauncher, and Xiaomi'scom.mitv.tvhome tools/disable.shapplies the same rule before disabling anything: if the list contains the app that owns Home and no other app answers HOME, it skips that entry and says why, then carries on with the rest- The setup wizard, settings apps, a vendor
FallbackHomeand factory-test apps also answer HOME, but don't count - If Home doesn't land on the new launcher after install, the script rolls back
Google TV adds a trap: the setup wizard setupwraith can take Home and crash-loop the system once the stock launcher is disabled, so it must be disabled too. But if the Wi-Fi network was saved during setup, that network belongs to setupwraith and disabling it deletes the network. So disable.sh checks first and skips it until you re-join Wi-Fi.
Each of these if branches looks like it came from a real incident.
Restore: Write the Record Before Touching Anything
Before tools/disable.sh changes anything, it writes down what the TV looked like in ~/.cleanyourtv/, one file per TV and list:
- For every package in the list: enabled, already disabled, or not installed
- Which component owned Home
- The three animation scales
Restore replays that record, so a package you disabled yourself stays disabled and Home returns to the component that owned it. A second run of the same list keeps the first record rather than overwriting it with the cleaned-up state.
Without a record (an older run, or a deleted file) the script says so and falls back to enabling the whole list and resetting scales to 1.0.
If the TV is unreachable, its own Settings → Apps page can re-enable the packages too.
The Launcher: 523 KB of Plain Java
The launcher is the other half of the project:
- About 523 KB, plain Java, built for TVs with 1 GB of RAM
- No blur, no video, no network permission, no background services
- The TV needs Android 8.0 (API 26) or newer;
minSdkis a compile-time floor, and the install script asks the TV forro.build.version.sdkfirst, so an older set gets both numbers instead of a failedpm install
"No network permission" matters for a tool that promises to remove telemetry: the launcher simply cannot send data out.
Configuration has three layers:
| Layer | Contents |
|---|---|
config.xml | Dock order, hidden apps, Live TV app, 4 to 7 tiles per row, reduced motion |
Theme config.json | The same keys plus background colour and wallpaper, pushed over Wi-Fi with no rebuild |
| Launcher settings on the TV | Hold OK on Settings: apps per row, dock opacity, animations, an app to open on start, and more |
Module Cards and Add-ons: Extension Points the User Approves
Any TV app can declare its own tile (label, caption, glow). The launcher asks you once per app, keeps it hidden by default, and remembers the answer tied to that app's signing key and card name. To change your mind, hold OK on Settings and choose Module cards.
Add-ons live in addons/ and plug in as module cards, never built into the launcher itself. tools/manage.py lists every add-on, theme and switch, shows what's on the TV, and installs, updates or removes one by running its creator's own script.
This "off by default, authorize one by one" model keeps the size and privacy promises from being quietly broken by add-ons.
Privacy Audit: Evidence, Not Guesses
tools/privacy.py addresses "which of these packages is listening?". The README is restrained about it: on many sets most packages run as android.uid.system, so fifty of them show RECORD_AUDIO: granted=true and none record anything; on others the microphone is in the remote, not the panel; and ACR (automatic content recognition) clients identify content from the picture and need only INTERNET.
So the tool lists voice, ACR and telemetry candidates in three groups, each with evidence:
- Named by the firmware's own
voice_interaction_service, a known component fromexamples/, or only a matching name - Whether it declares
RECORD_AUDIOand whether it shares the system UID - Whether AppOps history contains microphone access
--write privacy.txt turns identified candidates into a normal list that disable.sh and restore.sh already understand. Packages matched only by name stay out unless you pass --include-low.
The README is also upfront about the limits: it cannot prove intent. AppOps shows an op was touched, not what happened to the stream afterwards. Disabling an assistant has a real cost (the remote's mic button, voice search inside apps), which is why the report names that loss per package instead of calling it a win.
Drift Detection After a Firmware Update
A firmware update installs over the cleaned-up system: disabled packages come back, Home goes back to the stock launcher, and new preloads appear.
tools/check.py compares the TV with the list you applied, with meaningful exit codes:
| Exit code | Meaning |
|---|---|
0 | The TV still matches the list |
1 | Something drifted |
2 | The check could not run (TV did not answer, nobody accepted the prompt, list path missing, and so on) |
--fix reapplies the list: it switches Home to a launcher the list does not disable, disables the packages that came back, and reads the TV back to confirm. It never writes a new recovery record of its own, because only the first run's record holds the pre-cleanup state; when a record exists it adds to it first so restore.sh still returns to stock.
You can put the check in cron, say weekly. The docs honestly note the trade-off: a job like that needs the TV to keep network ADB listening, and network ADB is itself a security risk.
Performance Tooling: Making "Smooth" Measurable
The repo ships tools just for measuring the launcher:
tools/bench.py: key latency, focus movement, janky frames, cold start, return to Home, and idle CPU and PSS; changes nothing on the TV and writes raw per-key numbers to JSONtools/trace.py/trace_report.py: records Perfetto traces and reports where time goestools/flamechart.py: draws before/after flame charts for pull requeststools/screendiff.py: pixel-diffs before and after screenshots and blurs your Wi-Fi name
The tests/ directory holds 170+ files, from ADB key permissions to list paths to checking that numbers in the docs match examples/. Tables (brand counts, the TV list) are generated by tools/gen_tables.py from each folder's tv.json, so the README's numbers aren't hand-edited. For a repo that took in hundreds of contributors in nine days, these automated checks are part of why it hasn't fallen apart.
Scope and Limits
The README is candid here, and it's worth listing:
- Fire TV: only the debloat half works, because Fire OS will not hand Home to a third-party launcher; on the 2015 Fire TV Box (Fire OS 5) even that half fails, as every
pmroute is refused - A few China-market TCL sets: refuse to install any launcher; their lists say so in the header
- Samsung (Tizen) and LG (webOS): different systems, not supported; SHOWCASE.md has three webOS ports, and a 2021 Samsung set has no ADB and therefore no
pm disable-user - Network ADB is plaintext: it listens on port 5555, and on firmware with
ro.adb.secure=0any device on the LAN gets a shell, so close it when done and verify withtools/adb-closed.py - The risk is disabling something the TV leans on: hence small batches and a restore script at hand; if the TV no longer starts far enough for ADB, a factory reset from recovery is usually the way back, which also wipes your own apps and accounts
- No prebuilt APK: you must build it yourself; the author's reasoning is that you should control what goes on your TV
- In-app ads are mostly out of scope: you can point Android's Private DNS at a resolver like AdGuard DNS, but then that resolver sees every DNS query the TV makes, and it does not remove YouTube ads, which come from the same servers as the videos
One more thing to judge for yourself: handing a coding assistant a shell on your TV is itself a grant of authority. Read PROMPT.md and tools/disable.sh first, then decide how much to delegate.
Links and Resources
Official
- 🌟 GitHub: https://github.com/Gathin23/cleanyourtv
- 🌐 Website: https://cleanyour.tv
- 📚 Troubleshooting:
docs/TROUBLESHOOTING.mdin the repo - 💬 Discussions: GitHub Discussions
- 🐛 Issues: https://github.com/Gathin23/cleanyourtv/issues
Related
- Community phone app: cleanyour.tv/app
- Themes and add-ons: cleanyour.tv/addons
- Derived projects:
SHOWCASE.mdin the repo - Doing it for family remotely:
docs/REMOTE.mdin the repo
Summary and Outlook
Key Takeaways
- Disable, don't uninstall:
pm disable-useris the same switch as Settings → Disable, and combined with a write-first restore record it keeps the whole flow reversible - The assistant discovers, the scripts keep it safe: per-brand differences go to the AI on the spot, while Home protection, backup and rollback are fixed in scripts
- The launcher is deliberately restrained: 523 KB, plain Java, no network permission, and every extension is off by default and approved one by one
- Community lists are the moat: one folder per TV, plus generated tables and many tests, keep growth from getting out of hand
- The edges are stated plainly: limits on Fire TV, Samsung and LG, and the risk of network ADB, are all in the docs
Who It's For
- Anyone who wants to clean up their own Android TV or TV box, especially if the home-screen ads and recommendation rows bother them
- Developers curious how "AI coding assistant + restricted toolset" lands on real hardware
- Android TV launcher developers looking at its config and theme mechanisms
- People whose TV isn't in the list yet and who are willing to contribute one
Suggestions
Find your model under examples/ first and read its debloat.txt to see what would be disabled, then decide whether to let the assistant do it. On your first run, keep the restore record, and turn debugging back off on the TV when you're finished.
Explore PrimeSkills — curated AI agent and skill tools, each validated in real workflows. No hype, just tools that actually work.
Visit my homepage for more insights and interesting products.