<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: ILIA KARPENKO</title>
    <description>The latest articles on DEV Community by ILIA KARPENKO (@ghost_wayne).</description>
    <link>https://dev.to/ghost_wayne</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4205782%2F467fc57d-5bac-4659-a137-7b12c3b16ef0.jpg</url>
      <title>DEV Community: ILIA KARPENKO</title>
      <link>https://dev.to/ghost_wayne</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ghost_wayne"/>
    <language>en</language>
    <item>
      <title>Queue heavy builds for parallel Claude Code agents</title>
      <dc:creator>ILIA KARPENKO</dc:creator>
      <pubDate>Thu, 05 Nov 2026 17:52:14 +0000</pubDate>
      <link>https://dev.to/ghost_wayne/queue-heavy-builds-for-parallel-claude-code-agents-3832</link>
      <guid>https://dev.to/ghost_wayne/queue-heavy-builds-for-parallel-claude-code-agents-3832</guid>
      <description>&lt;p&gt;Say four Claude Code agents run on one laptop. One starts &lt;code&gt;cargo test&lt;/code&gt; while the other three already build. Four heavy jobs at once can slow the machine to a crawl, and you cannot watch every command the agents run.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;agentgc is a CLI that I built. Its Claude Code hook queues heavy commands. Install it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agentgc hook install           # dry run: prints the target file and the JSON
agentgc hook install --apply   # merges the hook into .claude/settings.json
# then restart Claude Code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A rule in &lt;code&gt;CLAUDE.md&lt;/code&gt; is only advice. A hook makes Claude Code follow it.&lt;/p&gt;

&lt;p&gt;The hook watches the Bash tool. It rewrites a plain heavy command, such as &lt;code&gt;cargo test&lt;/code&gt; or &lt;code&gt;npm run build&lt;/code&gt;, to &lt;code&gt;agentgc run -- cargo test&lt;/code&gt;. By default, a quarter of the logical cores (at least one) run heavy work at once. The rest wait for a free slot, in no fixed order.&lt;/p&gt;

&lt;p&gt;A second hook, &lt;code&gt;session-start&lt;/code&gt;, tells each new session to use &lt;code&gt;agentgc run --&lt;/code&gt; for heavy commands.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safe by default
&lt;/h2&gt;

&lt;p&gt;The hook asks for approval before it rewrites a command. Claude Code shows the new command, and you approve it. &lt;code&gt;--allow&lt;/code&gt; skips that question. Add it only if you accept every rewrite.&lt;/p&gt;

&lt;p&gt;The hook rewrites plain single commands only. Commands with shell syntax, such as pipes, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;, redirects, quotes or globs, stay as they are. Before it changes the file, &lt;code&gt;hook install&lt;/code&gt; copies your &lt;code&gt;.claude/settings.json&lt;/code&gt; to &lt;code&gt;settings.json.agentgc.bak&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The release notes say the tests pass on Windows, Linux and macOS in GitHub Actions. They also say the full flow was run end to end by hand on Windows only. The binaries are not code signed, so Windows SmartScreen or macOS Gatekeeper can warn on the first start.&lt;/p&gt;

&lt;h2&gt;
  
  
  New in 0.3.0
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;agentgc task review NAME&lt;/code&gt; shows what a task changed before you finish it. It only reads.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;agentgc doctor&lt;/code&gt; lists hard-coded ports and database names in the files that git tracks. It only reads.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;agentgc run --min-interval&lt;/code&gt; waits a set number of seconds between the starts of two queued commands.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;db.disconnect&lt;/code&gt; in &lt;code&gt;agentgc.task.toml&lt;/code&gt; runs your command before the database drop in &lt;code&gt;task done&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;agentgc worktrees --deps&lt;/code&gt; estimates how much a shared dependency store would save.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/JohnWayneeee/agentgc" rel="noopener noreferrer"&gt;https://github.com/JohnWayneeee/agentgc&lt;/a&gt;. Release notes: &lt;a href="https://github.com/JohnWayneeee/agentgc/releases/tag/v0.3.0" rel="noopener noreferrer"&gt;https://github.com/JohnWayneeee/agentgc/releases/tag/v0.3.0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>productivity</category>
      <category>git</category>
    </item>
    <item>
      <title>Parallel AI Coding Agents in Git Worktrees: How to Stop the Collisions</title>
      <dc:creator>ILIA KARPENKO</dc:creator>
      <pubDate>Wed, 04 Nov 2026 07:21:54 +0000</pubDate>
      <link>https://dev.to/ghost_wayne/parallel-ai-coding-agents-in-git-worktrees-how-to-stop-the-collisions-4gb</link>
      <guid>https://dev.to/ghost_wayne/parallel-ai-coding-agents-in-git-worktrees-how-to-stop-the-collisions-4gb</guid>
      <description>&lt;p&gt;Run three AI coding agents on one machine, each in its own git worktree, and the code stays separate. Everything around the code does not.&lt;/p&gt;

&lt;p&gt;Two dev servers try to bind port 3000, and one of them fails. Two tasks write to the same database, so one agent's test rows appear in the other agent's run. Three builds start at the same moment and the machine freezes. Finished task folders stay on disk, while package caches, browser downloads and temp files fill the drive.&lt;/p&gt;

&lt;p&gt;Git keeps the files apart. It does not keep ports, databases, processes or disk space apart. You can fix most of this with no tool at all. Here is the manual version first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: one worktree per task
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git worktree add -b feature-login ../myapp-feature-login main
&lt;span class="nb"&gt;cd&lt;/span&gt; ../myapp-feature-login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;-b&lt;/code&gt; creates a new branch from &lt;code&gt;main&lt;/code&gt;. Each task gets its own folder and branch. Your main checkout stays as it is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: one env file per task, with its own port
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;.env.local&lt;/code&gt; in each worktree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3101&lt;/span&gt;
&lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//localhost/myapp_feature_login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next task gets &lt;code&gt;PORT=3102&lt;/code&gt;. Check how your dev server reads its port. Some frameworks read &lt;code&gt;.env.local&lt;/code&gt;. Others take a flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: one database per task, inside one Postgres server
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;createdb myapp_feature_login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, in &lt;code&gt;psql&lt;/code&gt;: &lt;code&gt;CREATE DATABASE myapp_feature_login;&lt;/code&gt;. Run the migrations against that database. One server holds all the tasks. You do not start a second Postgres instance for each agent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: run heavy commands one at a time
&lt;/h2&gt;

&lt;p&gt;On Linux, &lt;code&gt;flock&lt;/code&gt; takes an exclusive lock on a file. The kernel drops the lock when the process dies, so a crash leaves no stale lock:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;flock /tmp/build.lock npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;flock&lt;/code&gt; waits until the lock is free. Stock macOS has no &lt;code&gt;flock&lt;/code&gt;. On macOS and in Git Bash, use a directory lock. &lt;code&gt;mkdir&lt;/code&gt; either creates the folder or fails, so only one shell wins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;until&lt;/span&gt; mkdir /tmp/build.lock 2&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/dev/null&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; sleep 2&lt;span class="o"&gt;;&lt;/span&gt; &lt;span class="k"&gt;done&lt;/span&gt;
npm run build
rmdir /tmp/build.lock
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The crash caveat applies to &lt;code&gt;mkdir&lt;/code&gt; only. If the build crashes or you close the terminal, &lt;code&gt;rmdir&lt;/code&gt; never runs. Delete &lt;code&gt;/tmp/build.lock&lt;/code&gt; by hand before the next build.&lt;/p&gt;

&lt;p&gt;agentgc &lt;code&gt;run&lt;/code&gt; uses OS file locks (flock on Unix, LockFileEx on Windows), so it has no stale lock.&lt;/p&gt;

&lt;h2&gt;
  
  
  What gets hard by hand
&lt;/h2&gt;

&lt;p&gt;Steps 1 to 4 hold up while the task count stays small. As it grows, four chores pile up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cleanup.&lt;/strong&gt; &lt;code&gt;git worktree remove&lt;/code&gt; refuses while a shell or an editor sits in the folder. On Windows, the folder stays locked until you find the program that holds it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port bookkeeping.&lt;/strong&gt; You keep a list of which port belongs to which task. A forgotten dev server keeps its port after its task ends.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Killing the right process.&lt;/strong&gt; On Windows, &lt;code&gt;netstat -ano | findstr :3101&lt;/code&gt; shows the PID. Then run &lt;code&gt;taskkill /PID &amp;lt;pid&amp;gt; /F&lt;/code&gt;. Check the PID first. A wrong PID stops someone else's work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies.&lt;/strong&gt; Each worktree holds its own &lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;.venv&lt;/code&gt; or &lt;code&gt;target&lt;/code&gt; folder. The disk use adds up for every task.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The same steps in agentgc
&lt;/h2&gt;

&lt;p&gt;agentgc is a garbage collector for the disk junk that CLI coding agents and dev tools leave behind: package caches, browser downloads, agent sessions and temp files. It also builds task environments: one worktree, free ports, one database name per task and an env file. The &lt;code&gt;task&lt;/code&gt; commands create all of that in one step. The &lt;code&gt;run&lt;/code&gt; command queues heavy work, and &lt;code&gt;up&lt;/code&gt; starts the services of a task.&lt;/p&gt;

&lt;p&gt;Download an archive for Windows, Linux or macOS (Apple Silicon) from the &lt;a href="https://github.com/JohnWayneeee/agentgc/releases/latest" rel="noopener noreferrer"&gt;latest release&lt;/a&gt;. Or build it from a clone of the repo with Rust: &lt;code&gt;cargo install --path .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Put the task settings in &lt;code&gt;agentgc.task.toml&lt;/code&gt; in the repo root. A short version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="k"&gt;[worktree]&lt;/span&gt;
&lt;span class="na"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"worktrees"&lt;/span&gt;
&lt;span class="na"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"main"&lt;/span&gt;

&lt;span class="k"&gt;[copy]&lt;/span&gt;
&lt;span class="na"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;".env.local"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;[ports]&lt;/span&gt;
&lt;span class="na"&gt;names&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"web"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3999&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;[db]&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"{repo}_{name}"&lt;/span&gt;
&lt;span class="na"&gt;create&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"createdb {db}"&lt;/span&gt;
&lt;span class="na"&gt;drop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"dropdb {db}"&lt;/span&gt;

&lt;span class="k"&gt;[env.dynamic]&lt;/span&gt;
&lt;span class="na"&gt;DATABASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"postgres://localhost/{db}"&lt;/span&gt;

&lt;span class="k"&gt;[setup]&lt;/span&gt;
&lt;span class="na"&gt;commands&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"npm install"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;dir = "worktrees"&lt;/code&gt; puts the worktrees in a folder inside the repo, so add that folder to &lt;code&gt;.gitignore&lt;/code&gt;. agentgc prints a hint when the folder is not ignored. It never edits &lt;code&gt;.gitignore&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;The commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;agentgc scan                                       &lt;span class="c"&gt;# read every path before any clean&lt;/span&gt;
agentgc task new feature-login                     &lt;span class="c"&gt;# dry run: prints the plan&lt;/span&gt;
agentgc task new feature-login --yes --run-setup   &lt;span class="c"&gt;# worktree, ports, database, setup&lt;/span&gt;
agentgc task list                                  &lt;span class="c"&gt;# ports, database and status per task&lt;/span&gt;
agentgc ps                                         &lt;span class="c"&gt;# processes per task, with RAM&lt;/span&gt;
agentgc ps --stop                                  &lt;span class="c"&gt;# dry run: idle dev servers, tests, builds&lt;/span&gt;
agentgc run -- npm &lt;span class="nb"&gt;test&lt;/span&gt;                            &lt;span class="c"&gt;# queued: heavy commands take turns&lt;/span&gt;
agentgc clean --dry-run                            &lt;span class="c"&gt;# junk from scan, item by item&lt;/span&gt;
agentgc task &lt;span class="k"&gt;done&lt;/span&gt; feature-login                    &lt;span class="c"&gt;# dry run: blockers and processes&lt;/span&gt;
agentgc task &lt;span class="k"&gt;done&lt;/span&gt; feature-login --yes              &lt;span class="c"&gt;# removes worktree, task files, merged branch&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;task new&lt;/code&gt; without &lt;code&gt;--yes&lt;/code&gt; only prints the plan. The file &lt;code&gt;.agentgc/task.env&lt;/code&gt; holds &lt;code&gt;PORT_WEB&lt;/code&gt; and &lt;code&gt;DATABASE_URL&lt;/code&gt;, so your dev server must read that file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Safety model
&lt;/h2&gt;

&lt;p&gt;Only two commands delete: &lt;code&gt;task done --yes&lt;/code&gt; and &lt;code&gt;clean&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dry run first.&lt;/strong&gt; &lt;code&gt;task new&lt;/code&gt;, &lt;code&gt;task done&lt;/code&gt; and &lt;code&gt;ps --stop&lt;/code&gt; print a plan and change nothing until you add &lt;code&gt;--yes&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blockers stop &lt;code&gt;task done&lt;/code&gt;.&lt;/strong&gt; It refuses while the worktree holds uncommitted files or commits that are neither merged nor pushed. &lt;code&gt;--force&lt;/code&gt; overrides both checks and prints what would be lost.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Item by item.&lt;/strong&gt; &lt;code&gt;clean&lt;/code&gt; asks about each item. A safe item needs a &lt;code&gt;y&lt;/code&gt;. A risky item needs you to type its ID. Risky items go to the Recycle Bin, not to permanent delete.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guards.&lt;/strong&gt; &lt;code&gt;clean&lt;/code&gt; refuses paths that hold a &lt;code&gt;.git&lt;/code&gt; entry, and paths named Documents, Downloads or User Data, among others.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idle only.&lt;/strong&gt; &lt;code&gt;ps --stop&lt;/code&gt; touches only idle dev servers, language servers, tests and builds. Agents, databases and other processes keep running.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Config runs commands.&lt;/strong&gt; &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;drop&lt;/code&gt; and &lt;code&gt;setup.commands&lt;/code&gt; run as you, without a shell. Read &lt;code&gt;agentgc.task.toml&lt;/code&gt; like a Makefile before you use &lt;code&gt;--run-setup&lt;/code&gt; or &lt;code&gt;task done --yes&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Honest limits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built and covered by automated tests on Windows, Linux and macOS in GitHub Actions. Windows is the only system where the full flow was run end to end. The release binaries are not code signed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;agentgc up&lt;/code&gt; starts the services listed for a task. It is opt-in and installs no system service. Nothing starts at boot or login.&lt;/li&gt;
&lt;li&gt;agentgc never starts containers, never runs Docker and never talks to a database server.&lt;/li&gt;
&lt;li&gt;On Windows, &lt;code&gt;ps --stop --yes&lt;/code&gt; stops nothing without &lt;code&gt;--force&lt;/code&gt;, because agentgc has no graceful stop on Windows.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;run&lt;/code&gt; is not fair. Whoever finds a free slot first gets it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Proof
&lt;/h2&gt;

&lt;p&gt;After one cleanup session on 2026-11-04, free space on my Windows machine went from about 6 GB to about 180 GB. This is my own statement. It is not a measurement by agentgc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credit
&lt;/h2&gt;

&lt;p&gt;The queue idea behind &lt;code&gt;run&lt;/code&gt; comes from &lt;a href="https://github.com/mokevnin/heavy" rel="noopener noreferrer"&gt;heavy&lt;/a&gt; by mokevnin, a counting semaphore for macOS and Linux. agentgc's &lt;code&gt;run&lt;/code&gt; is separate code. It adds Windows support and named resources, such as one phone or one browser profile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next step
&lt;/h2&gt;

&lt;p&gt;If you run agents in parallel and want fewer collisions, star the repo: &lt;a href="https://github.com/JohnWayneeee/agentgc" rel="noopener noreferrer"&gt;https://github.com/JohnWayneeee/agentgc&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Telegram channel &lt;a href="https://t.me/+pWGhdQdw5DZmYzYy" rel="noopener noreferrer"&gt;https://t.me/+pWGhdQdw5DZmYzYy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>git</category>
      <category>devtools</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Was Binance Hacked? What the Onchain Data Shows (October 29, 2026)</title>
      <dc:creator>ILIA KARPENKO</dc:creator>
      <pubDate>Thu, 29 Oct 2026 23:27:37 +0000</pubDate>
      <link>https://dev.to/ghost_wayne/was-binance-hacked-what-the-onchain-data-shows-october-29-2026-50kl</link>
      <guid>https://dev.to/ghost_wayne/was-binance-hacked-what-the-onchain-data-shows-october-29-2026-50kl</guid>
      <description>&lt;p&gt;&lt;em&gt;Updated: Oct 29, 2026, 23:20 UTC&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;An EIP-7702 delegation came first. 167,464 ETH left Binance 14 3 minutes and 24 seconds later.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Was Binance hacked? Binance has not confirmed a cause, but Etherscan labels the sender of the 167,464 ETH transfer "Binance Hot Wallet Exploiter," CZ wrote "It does look like a hack on Binance," and Binance wrote of a "potential security issue" with no amount. The steps below give each transaction with its time, source and screenshot, what is not known, and how you can check it yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Was Binance Hacked? What the EIP-7702 Delegation Shows
&lt;/h2&gt;

&lt;p&gt;Binance has not confirmed a cause. Here is what the chain shows. All times are UTC.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1. Funding, Oct 28 and Oct 29.&lt;/strong&gt; The initiator, 0x7C8601d4645b93cea45F71e118A729332e6B5CA0, received 0.1 ETH from the Tornado.Cash pool on Oct 28 at 07:39 and 08:53 UTC, and on Oct 29 at 08:23 UTC. Etherscan labels the address "Binance Hot Wallet Exploiter."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1pm_F7DXf-_eQJabem3WvjUgFkeGyPiUC" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1pm_F7DXf-_eQJabem3WvjUgFkeGyPiUC" alt="Etherscan address page of the initiator with the label and the Tornado.Cash funding" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan, initiator address, read 21:34-21:38 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2. Contract created, 15:59:11 UTC.&lt;/strong&gt; The initiator creates contract 0x63e842B054Bd624a465454D533C33F573e9c6fAe. Its source code is not verified on Etherscan. &lt;a href="https://etherscan.io/tx/0x97408e7562eb2b28efcd24ba01609607b5749bc89448d007fa8b50ecf290329c" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3. EIP-7702 delegation, 20:20:59 UTC.&lt;/strong&gt; The initiator sends a transaction that Etherscan describes as "EIP-7702: Binance 14 Delegate to 0x63e842B0...73e9c6fAe." A delegation needs an authorization signed by the key of Binance 14. How that signature was obtained is not known. &lt;a href="https://etherscan.io/tx/0xad99264d5532ae0dd04b2004eebda05f25657e70dacb764f7ac8d4ccd051298b" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1r00QRdgw69a95q616p7es1VbAyEk7Rpa" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1r00QRdgw69a95q616p7es1VbAyEk7Rpa" alt="Etherscan transaction page with the EIP-7702 action &amp;quot;Binance 14 Delegate to 0x63e842B0...73e9c6fAe&amp;quot; at 20:20:59 UTC" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan transaction 0xad9926…298b, read 21:34-21:38 UTC, Oct 29, 2026. Transaction time: 20:20:59 UTC.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4. 167,464.25 ETH out, 20:24:23 UTC.&lt;/strong&gt; Three minutes and 24 seconds after step 3, Binance 14 sends 167,464.25 ETH and dozens of tokens to 0x5227…2f8c. Etherscan labels that address "Binance Hot Wallet Exploiter 2." &lt;a href="https://etherscan.io/tx/0x53bd38b816c23e74134786c29a8c18d792777998a3b9326047b583100e88e2f3" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1kbsy4HCByCvfMDDqbg-UfZhDIcDRa5Ky" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1kbsy4HCByCvfMDDqbg-UfZhDIcDRa5Ky" alt="Etherscan transaction page for the transfer of 167,464.25 ETH from Binance 14 at 20:24:23 UTC" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan transaction 0x53bd38…e2f3, read 21:34-21:38 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5. USDC out of Hot Wallet 34, 20:41:23 and 20:59:47 UTC.&lt;/strong&gt; The initiator calls Binance 14 a second time. 780M USDC and 43M USDC leave "Binance: Hot Wallet 34" for 0x5227. The total is 823M USDC. &lt;a href="https://etherscan.io/tx/0xdc102dd89dded5a83f1008906883ffb7c81ff3b7d7965d8c7277d170b5e17481" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1TPuB_xnB28ZaHCSUnVkgH7RwfEwOUO-S" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1TPuB_xnB28ZaHCSUnVkgH7RwfEwOUO-S" alt="Etherscan transaction page for the transfer of 780M USDC from Binance Hot Wallet 34 at 20:41:23 UTC" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan transaction 0xdc102d…7481, read Oct 29, 2026 (transfer time 20:41:23 UTC).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6. Delegation on, 21:36 and 21:53 UTC.&lt;/strong&gt; At 21:36 UTC the Etherscan page for Binance 14 shows "Delegated to 0x63e842B0...73e9c6fAe," and a 41.49 ETH deposit is pending. At 21:53 UTC the delegation was on when we checked.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1QWn5d9KH28Qd1w8Et0kclq1r4Xx-tgeN" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1QWn5d9KH28Qd1w8Et0kclq1r4Xx-tgeN" alt="Etherscan page for Binance 14 with the line &amp;quot;Delegated to 0x63e842B0...73e9c6fAe&amp;quot;" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan address page for Binance 14, read at 21:36 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the chain shows and what it does not.&lt;/strong&gt; The chain shows the sequence and the times. It does not show how the key signature was obtained, who controls the initiator, or whether Binance has verified any of this. Etherscan labels name addresses. They do not name owners.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full timeline (UTC)
&lt;/h2&gt;

&lt;p&gt;All times are UTC on October 29, 2026, unless the row gives another date. Each row names its source.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Time (UTC)&lt;/th&gt;
&lt;th&gt;What the chain or a source shows&lt;/th&gt;
&lt;th&gt;Source&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Oct 28, 07:39 and 08:53&lt;/td&gt;
&lt;td&gt;Initiator 0x7C86…5CA0 is funded from the Tornado.Cash 0.1 ETH pool&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/address/0x7C8601d4645b93cea45F71e118A729332e6B5CA0" rel="noopener noreferrer"&gt;Etherscan&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Oct 29, 08:23&lt;/td&gt;
&lt;td&gt;Same initiator, same pool, 0.1 ETH&lt;/td&gt;
&lt;td&gt;Same page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15:59:11&lt;/td&gt;
&lt;td&gt;Initiator creates contract 0x63e8…6fAe. Its source code is not verified on Etherscan&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tx/0x97408e7562eb2b28efcd24ba01609607b5749bc89448d007fa8b50ecf290329c" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:20:59&lt;/td&gt;
&lt;td&gt;EIP-7702 transaction from the initiator. Etherscan action: "Binance 14 Delegate to 0x63e842B0...73e9c6fAe"&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tx/0xad99264d5532ae0dd04b2004eebda05f25657e70dacb764f7ac8d4ccd051298b" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:24:23&lt;/td&gt;
&lt;td&gt;Binance 14 sends 167,464.25 ETH to 0x5227…2f8c, with dozens of tokens&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tx/0x53bd38b816c23e74134786c29a8c18d792777998a3b9326047b583100e88e2f3" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:24:47&lt;/td&gt;
&lt;td&gt;Binance 16 sends 55.7M USDT, 25.9M RLUSD and other tokens to 0x5227&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tokentxns?a=0x5227f603c1ee34ce3c06efe6477003bdfccb2f8c" rel="noopener noreferrer"&gt;Etherscan token transfers of 0x5227&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:30:11&lt;/td&gt;
&lt;td&gt;500M USDT to 0x9749…C762. Within 30 minutes it splits into eight transfers&lt;/td&gt;
&lt;td&gt;Etherscan token transfers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:30:34&lt;/td&gt;
&lt;td&gt;Arbitrum: Binance 54 sends 74,559,805.2 ARB to 0x5227&lt;/td&gt;
&lt;td&gt;&lt;a href="https://arbiscan.io/tx/0xa18e57027dae90de066ac093bbb4ae3d63598accbe5175cdf4195c686462edff" rel="noopener noreferrer"&gt;Arbiscan&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:33:23&lt;/td&gt;
&lt;td&gt;200M USDT to 0x0Ddf…697e&lt;/td&gt;
&lt;td&gt;Etherscan token transfers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:38:47&lt;/td&gt;
&lt;td&gt;195,460 ETH to an address labeled "Binance Hot Wallet Exploiter 8"&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tx/0x551d7961652e6d9835b11988908adf86ebe480badb4ce2d7d52193b2b1b02c76" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:41:23&lt;/td&gt;
&lt;td&gt;780M USDC from "Binance: Hot Wallet 34" to 0x5227&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tx/0xdc102dd89dded5a83f1008906883ffb7c81ff3b7d7965d8c7277d170b5e17481" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:52:59&lt;/td&gt;
&lt;td&gt;190M USDT from 0x0Ddf…697e to an address labeled "Binance Hot Wallet Exploiter 3"&lt;/td&gt;
&lt;td&gt;Etherscan token transfers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20:59:47&lt;/td&gt;
&lt;td&gt;43M USDC from Hot Wallet 34 to 0x5227. Total from Hot Wallet 34: 823M USDC&lt;/td&gt;
&lt;td&gt;Etherscan token transfers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:04:23&lt;/td&gt;
&lt;td&gt;Second sweep from Binance 14: small amounts and 3.9M USDT&lt;/td&gt;
&lt;td&gt;Etherscan token transfers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:13:44&lt;/td&gt;
&lt;td&gt;Whale Alert: an address with 823,000,000 USDC frozen&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/whale_alert/status/2115915008634663274" rel="noopener noreferrer"&gt;Whale Alert&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:15:23&lt;/td&gt;
&lt;td&gt;CZ: "It does look like a hack on Binance."&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/cz_binance/status/2115915423174853077" rel="noopener noreferrer"&gt;CZ&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:22:59&lt;/td&gt;
&lt;td&gt;88,541,065 RLUSD to 0x5C23…A00Fea4FC, forwarded at 21:25:59&lt;/td&gt;
&lt;td&gt;Etherscan token transfers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:29:09&lt;/td&gt;
&lt;td&gt;Binance: "potential security issue"&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/binance/status/2115918888429133902" rel="noopener noreferrer"&gt;Binance&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:31:37&lt;/td&gt;
&lt;td&gt;Whale Alert: 174,999,872 USDT frozen at an address&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/whale_alert/status/2115919507990397104" rel="noopener noreferrer"&gt;Whale Alert&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:33&lt;/td&gt;
&lt;td&gt;DeBank shows $2.34B for 0x5227 (it showed $2.42B at about 21:05)&lt;/td&gt;
&lt;td&gt;&lt;a href="https://debank.com/profile/0x5227f603c1ee34ce3c06efe6477003bdfccb2f8c" rel="noopener noreferrer"&gt;DeBank&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:36&lt;/td&gt;
&lt;td&gt;Binance 14 page shows "Delegated to 0x63e842B0...73e9c6fAe." A 41.49 ETH deposit is pending&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/address/0x28C6c06298d514Db089934071355E5743bf21d60" rel="noopener noreferrer"&gt;Etherscan&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:36:30&lt;/td&gt;
&lt;td&gt;Arbitrum: 0x5227 sends all 74,559,805.2 ARB to 0x3E2b…32d5&lt;/td&gt;
&lt;td&gt;&lt;a href="https://arbiscan.io/tx/0xa18e57027dae90de066ac093bbb4ae3d63598accbe5175cdf4195c686462edff" rel="noopener noreferrer"&gt;Arbiscan&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:38&lt;/td&gt;
&lt;td&gt;Binance's post is edited. The new text adds an update promise and a scam warning&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/binance/status/2115918888429133902" rel="noopener noreferrer"&gt;Binance&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:42:33&lt;/td&gt;
&lt;td&gt;Watcher.Guru posts "Binance hacked with over $5.6 billion stolen," with a breakdown by asset&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/WatcherGuru/status/2115922259739349132" rel="noopener noreferrer"&gt;Watcher.Guru&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21:53&lt;/td&gt;
&lt;td&gt;Delegation active for Binance 14&lt;/td&gt;
&lt;td&gt;Etherscan check, see step 6&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22:15:56&lt;/td&gt;
&lt;td&gt;A post on X says USD1 has frozen $27M associated with the Binance incident&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/ZachWitkoff/status/2115930660166860922" rel="noopener noreferrer"&gt;Post on X&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22:23:14&lt;/td&gt;
&lt;td&gt;CZ: "Loss might be a bit higher than that, but will cover."&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/cz_binance/status/2115932500006756686" rel="noopener noreferrer"&gt;CZ&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22:33:11&lt;/td&gt;
&lt;td&gt;Binance: security checks; withdrawals paused until the security issue is fully resolved&lt;/td&gt;
&lt;td&gt;&lt;a href="https://x.com/binance/status/2115935002139742437" rel="noopener noreferrer"&gt;Binance&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;From about 22:58&lt;/td&gt;
&lt;td&gt;Binance 14 sends its tokens one per block to "Binance: Cold Wallet 20"&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tx/0x33b534fce40ab0830cf6e269b1a6e3676762f1a431255d6f2a2563ddbecf1654" rel="noopener noreferrer"&gt;Etherscan, COVER transfer&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23:03:47&lt;/td&gt;
&lt;td&gt;8,405,741.58 SNX moved from 0x5227 to "Synthetix: protocolDAO"&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/tx/0x0d4a20dd52946d5d15292161522daf475a6a971bff815dd5fb6623d23caf776f" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23:04&lt;/td&gt;
&lt;td&gt;Binance 14 shows "Delegated to 0x63e842B0...73e9c6fAe"; ETH 0.94, tokens over $919K&lt;/td&gt;
&lt;td&gt;&lt;a href="https://etherscan.io/address/0x28C6c06298d514Db089934071355E5743bf21d60" rel="noopener noreferrer"&gt;Etherscan&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  How an EIP-7702 delegation works, in plain words
&lt;/h2&gt;

&lt;p&gt;An Ethereum wallet is controlled by one private key. EIP-7702 lets that key sign an authorization that tells the wallet to run the code of a chosen contract. The wallet keeps its own balances. The contract's code is not copied into the wallet. It runs on the wallet's assets while the delegation is set.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://eips.ethereum.org/EIPS/eip-7702" rel="noopener noreferrer"&gt;EIP-7702 specification&lt;/a&gt; says the account being delegated signs each authorization, and the sender of the transaction pays for it. A new authorization that points to the zero address clears the delegation. So the key has to sign a new authorization to remove it.&lt;/p&gt;

&lt;p&gt;In this case, the Etherscan action at 20:20:59 UTC reads "EIP-7702: Binance 14 Delegate to 0x63e842B0...73e9c6fAe." The transaction sender is labeled "Binance Hot Wallet Exploiter." By the spec, the authorization needs a signature from the key of the delegated account. So the signature must come from Binance 14's key. How that signature was produced is not known.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the funds went
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ETH, 20:24:23 UTC.&lt;/strong&gt; See step 4 above. 167,464.25 ETH went from Binance 14 to 0x5227…2f8c. Etherscan labels that address "Binance Hot Wallet Exploiter 2." We give amounts in ETH and tokens. Sources give different USD values for the same ETH, so we leave USD out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;USDC, 20:41:23 and 20:59:47 UTC.&lt;/strong&gt; See step 5 above. 780M USDC and 43M USDC went from "Binance: Hot Wallet 34" to 0x5227. The total is 823M USDC.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ETH, 20:38:47 UTC.&lt;/strong&gt; 195,460 ETH went to the address labeled "Binance Hot Wallet Exploiter 8" (0x8532…43D4). Etherscan showed a balance of 195,460 ETH there at 21:31 UTC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F19nSakmVT5Hs2QF5Dv9gE_R4Voi-pYZps" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F19nSakmVT5Hs2QF5Dv9gE_R4Voi-pYZps" alt="Etherscan transaction page for the transfer of 195,460 ETH at 20:38:47 UTC" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan transaction 0x551d79…2c76, Oct 29, 2026 (transfer time 20:38:47 UTC).&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;USDT, 20:30:11 and 20:33:23 UTC.&lt;/strong&gt; 500M USDT went to 0x9749…C762 and split into eight transfers within 30 minutes. 200M USDT went to 0x0Ddf…697e. At 20:47:47 about 10M USDT was swapped on Uniswap pools. At 20:52:59, 190M USDT went to the address labeled "Binance Hot Wallet Exploiter 3."&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ARB on Arbitrum, 20:30:34 UTC.&lt;/strong&gt; Binance 54 sent 74,559,805.2 ARB to 0x5227 in a plain transfer, with no delegation. At 21:36:30 UTC, 0x5227 sent all of it to 0x3E2b…32d5.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1dNYO2zB66SiIcLomO-FH9SImHurSK1yY" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1dNYO2zB66SiIcLomO-FH9SImHurSK1yY" alt="Arbiscan page for the 74,559,805.2 ARB transfer from Binance 54 at 20:30:34 UTC" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Arbiscan, read 21:39 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Balances.&lt;/strong&gt; At 21:33 UTC, DeBank showed $2.34B for 0x5227, including 975.07M USDT and 823M USDC. At 21:30 UTC, Etherscan listed $2.27B in tokens and 1,708.24 ETH for the same address.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Movements from 0x5227 are not all made by 0x5227. Check the sender of each transaction before you read it as the exploiter's action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Freezes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;USDC, 21:13:44 UTC.&lt;/strong&gt; Whale Alert reported an address with 823,000,000 USDC frozen. The text names no address. The total matches the 823M USDC that Hot Wallet 34 sent to 0x5227. That match is ours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tether and Circle, 21:15:23 UTC.&lt;/strong&gt; CZ thanked Tether (~$971m) and Circle (~$823m) for the freezes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;USDT, 21:31:37 UTC.&lt;/strong&gt; Whale Alert reported 174,999,872 USDT frozen. The amount equals the 175M part of the 500M split from 0x9749…C762. That second match is ours.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1nC6cbkiW4Ed6lLEq-IgWCc5pWhHclzTT" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1nC6cbkiW4Ed6lLEq-IgWCc5pWhHclzTT" alt="Whale Alert post from 21:13:44 UTC reporting 823,000,000 USDC frozen" width="633" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Whale Alert on X, post at 21:13:44 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Are Binance User Funds Safe? What Binance and CZ Said
&lt;/h2&gt;

&lt;p&gt;At 21:15:23 UTC, CZ wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;User funds are safe! It does look like a hack on Binance. Appreciate the quick freeze from Tether (~$971m) and Circle (~$823m). I don't manage Binance (.com) anymore, but as a shareholder, I expect all user funds will be fully covered.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F12_WAHskfKomJ30EyXVyYtojB101nvbbs" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F12_WAHskfKomJ30EyXVyYtojB101nvbbs" alt="CZ post on X from 21:15:23 UTC" width="633" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: CZ on X, post at 21:15:23 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;At 21:29:09 UTC, Binance wrote:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Our teams are aware of reports of a potential security issue and are actively investigating. User funds are completely safe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At 21:38 UTC the post was edited. The new text adds: "we will provide updates through official Binance channels as soon as we have verified information. Users should remain cautious of scams."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F10kRMy_i_wsQerDU3_Jz62XpncL1kR4r0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F10kRMy_i_wsQerDU3_Jz62XpncL1kR4r0" alt="Binance post on X from 21:29:09 UTC" width="633" height="735"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Binance on X, post at 21:29:09 UTC, Oct 29, 2026 (screenshot taken after the 21:38 UTC edit).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Binance did not name a cause and gave no amount. CZ's post above uses the word "hack."&lt;/p&gt;

&lt;h2&gt;
  
  
  Did Binance Pause Withdrawals? What Binance Did Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Withdrawals paused, 22:33 UTC.&lt;/strong&gt; Binance wrote: "Our team is conducting security checks. Withdrawals will resume as soon as the security issue is fully resolved. User funds remain safe."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1px75Kv1B-7oIHqMz_-PZK-OpBKdn2D8E" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1px75Kv1B-7oIHqMz_-PZK-OpBKdn2D8E" alt="Binance post at 22:33:11 UTC announcing security checks and paused withdrawals" width="633" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold-wallet transfers, from about 22:58 UTC.&lt;/strong&gt; Binance 14 sends its tokens one per block to "Binance: Cold Wallet 20" (0xF977814e90dA44bFA03b6295A0616a897441aceC). USDT and WLFI transfers in that run revert. The destination is a Binance-labeled cold wallet. Who signs these transfers is not shown. Example: &lt;a href="https://etherscan.io/tx/0x33b534fce40ab0830cf6e269b1a6e3676762f1a431255d6f2a2563ddbecf1654" rel="noopener noreferrer"&gt;COVER transfer at 23:04:23 UTC&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1MDLeaPTaGBB7QYZABmWF5B8m1dVF_x5g" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1MDLeaPTaGBB7QYZABmWF5B8m1dVF_x5g" alt="Etherscan page for Binance 14 at 23:04 UTC, showing the delegation and remaining token holdings" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan, Binance 14 address page, read 23:04 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1fzV1Esjoy9Ney_dLszRUsHs9wOAYUKOq" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1fzV1Esjoy9Ney_dLszRUsHs9wOAYUKOq" alt="Etherscan transaction: COVER transfer from Binance 14 to Binance: Cold Wallet 20 at 23:04:23 UTC" width="1600" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Etherscan transaction 0x33b534…f1654, timestamp 23:04:23 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Delegation on, 23:04 UTC.&lt;/strong&gt; Binance 14 shows "Delegated to 0x63e842B0...73e9c6fAe." Its ETH balance was 0.94 at 23:04 UTC, against 305.2 at 21:36 UTC. Its token holdings were over $919K.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;USD1 froze $27M, 22:15:56 UTC.&lt;/strong&gt; A post on X said USD1 "has taken proactive steps to freeze the $27 million in USD1 associated with the &lt;a class="mentioned-user" href="https://dev.to/binance"&gt;@binance&lt;/a&gt; hack." CZ replied "Thank you!" at 22:25:59 UTC.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1-VY0jLxhnd_4u7E4oreVRRSI_lowiaee" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1-VY0jLxhnd_4u7E4oreVRRSI_lowiaee" alt="Post on X at 22:15:56 UTC about the USD1 freeze" width="633" height="841"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Synthetix, 23:03:47 UTC.&lt;/strong&gt; 8,405,741.58 SNX moved from 0x5227…2f8c to "Synthetix: protocolDAO" in a transaction sent by snax-governance.eth. The sender is on the issuer side. &lt;a href="https://etherscan.io/tx/0x0d4a20dd52946d5d15292161522daf475a6a971bff815dd5fb6623d23caf776f" rel="noopener noreferrer"&gt;Transaction&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is not known
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The signature.&lt;/strong&gt; The delegation needs a signature from Binance 14's key. How that signature was produced, and by whom, is not known.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The contract.&lt;/strong&gt; 0x63e842B0...73e9c6fAe is not verified on Etherscan. We do not know what its code does.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 167,464.25 ETH transfer.&lt;/strong&gt; The top of the Etherscan page shows "Error Occurred [execution reverted]" next to the To field, while the transaction status reads Success. On 2026-10-30 the Internal Txns tab listed the transfer without an error mark. We do not know why the page shows that note.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The total.&lt;/strong&gt; No official figure exists. Media figures disagree: $2.5B (PANews), $2.77B (CryptoBriefing) and $2.8B (Coindoo). We did not check them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Labels.&lt;/strong&gt; An Etherscan label names an address. It does not say who controls the address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Other chains.&lt;/strong&gt; We did not check Avalanche, where DeBank shows $24M for the same address. We did not read Arkham, which sits behind Cloudflare.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tron.&lt;/strong&gt; Whale Alert reported 65,990,000 USDT frozen on Tron at 21:22:15 UTC. We did not check whether it links to this case.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customer funds.&lt;/strong&gt; Binance says user funds are safe. Onchain data does not show Binance's customer balances, so we cannot check that claim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How Much Was Stolen From Binance? The $5.6B Claim
&lt;/h2&gt;

&lt;p&gt;Watcher.Guru posted at 21:42:33 UTC: "Binance hacked with over $5.6 billion stolen." Its breakdown: $1.45B BTC, $875M ETH, $234M TRX, $50M XAUT, $1.57B USDT, $823M USDC, $75M WBETH, $88.5M RLUSD and $447.5M of other assets. The breakdown includes chains we did not check, such as BTC and Tron. Binance has not confirmed it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1gHmN5YemTkm-rQdX5lXfbTz2MlfnpEgU" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1gHmN5YemTkm-rQdX5lXfbTz2MlfnpEgU" alt="Watcher.Guru post at 21:42:33 UTC with the $5.6 billion breakdown by asset" width="642" height="953"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Watcher.Guru on X, post at 21:42:33 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our figures are balances of one address on the chains Etherscan tracks, not a total. Etherscan showed $2.29B for 0x5227…2f8c at 22:26 UTC on October 29. Etherscan showed $2.21B (multichain portfolio) for the same address at 23:05 UTC. Neither figure is a total of stolen funds.&lt;/p&gt;

&lt;p&gt;A post by 0xngmi, quoted in a CZ post at 22:23:14 UTC, estimated the loss at about $1B after the USDT and USDC freezes. The same post said Binance holds $144B in custody. CZ replied: "Loss might be a bit higher than that, but will cover."&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1OrooeGobEnNHZqZPBg6KW8MprzvQRijq" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Flh3.googleusercontent.com%2Fd%2F1OrooeGobEnNHZqZPBg6KW8MprzvQRijq" alt="CZ post at 22:23:14 UTC: &amp;quot;Loss might be a bit higher than that, but will cover.&amp;quot;" width="633" height="349"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: CZ on X, post at 22:23:14 UTC, Oct 29, 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Binance has not published a total. Media figures disagree (see "What is not known"). Neither Binance nor CZ named a cause or a group in the posts we read (21:15 to 22:33 UTC). The sources we read name no country or group. Treat any attribution as unverified until an official source or a named investigator publishes evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to verify it yourself
&lt;/h2&gt;

&lt;p&gt;These checks are free. You need a browser. On Etherscan, open the timestamp menu and select "+UTC." Write down the time you read each page. Balances and labels change.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The delegation.&lt;/strong&gt; Open &lt;a href="https://etherscan.io/tx/0xad99264d5532ae0dd04b2004eebda05f25657e70dacb764f7ac8d4ccd051298b" rel="noopener noreferrer"&gt;the EIP-7702 transaction&lt;/a&gt;. Read the "Transaction Action" line. Open the Authorizations tab to see the signed authorization.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The delegated wallet.&lt;/strong&gt; Open &lt;a href="https://etherscan.io/address/0x28C6c06298d514Db089934071355E5743bf21d60" rel="noopener noreferrer"&gt;Binance 14&lt;/a&gt;. Look for the "Delegated to" line. Check whether it shows the same address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The sweep.&lt;/strong&gt; Open &lt;a href="https://etherscan.io/tx/0x53bd38b816c23e74134786c29a8c18d792777998a3b9326047b583100e88e2f3" rel="noopener noreferrer"&gt;the 167,464.25 ETH transaction&lt;/a&gt;. Compare the From and To labels. Open the Internal Txns tab and read the transfer line. Read the error note next to the To field.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The token flows.&lt;/strong&gt; Open &lt;a href="https://etherscan.io/tokentxns?a=0x5227f603c1ee34ce3c06efe6477003bdfccb2f8c" rel="noopener noreferrer"&gt;the token transfers of 0x5227&lt;/a&gt;. Sort by time and compare the token, the amount and the sender label of each row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The initiator.&lt;/strong&gt; Open &lt;a href="https://etherscan.io/address/0x7C8601d4645b93cea45F71e118A729332e6B5CA0" rel="noopener noreferrer"&gt;the initiator address&lt;/a&gt;. Look for the Tornado.Cash deposits in its transaction list.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The contract.&lt;/strong&gt; Open &lt;a href="https://etherscan.io/address/0x63e842B054Bd624a465454D533C33F573e9c6fAe" rel="noopener noreferrer"&gt;0x63e842B0...73e9c6fAe&lt;/a&gt;. Check whether the Contract tab shows verified source code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Arbitrum.&lt;/strong&gt; Open &lt;a href="https://arbiscan.io/tx/0xa18e57027dae90de066ac093bbb4ae3d63598accbe5175cdf4195c686462edff" rel="noopener noreferrer"&gt;the Arbiscan transaction&lt;/a&gt;. Check the 74,559,805.2 ARB transfers in and out of 0x5227.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The balance.&lt;/strong&gt; Open &lt;a href="https://debank.com/profile/0x5227f603c1ee34ce3c06efe6477003bdfccb2f8c" rel="noopener noreferrer"&gt;the DeBank profile of 0x5227&lt;/a&gt;. Write down the value and the time you read it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The rules.&lt;/strong&gt; Read the &lt;a href="https://eips.ethereum.org/EIPS/eip-7702" rel="noopener noreferrer"&gt;EIP-7702 specification&lt;/a&gt; for the authorization format and the zero-address rule.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Compare every address letter by letter. The address 0x9749…C762 has look-alike variants. Fake tokens use look-alike letters from other alphabets. A label on a page is a label. It is not proof of who controls the address.&lt;/p&gt;

&lt;p&gt;I post every update on this case in my Telegram channel: &lt;a href="https://t.me/IliaAIToolsBot?start=devto-binance" rel="noopener noreferrer"&gt;https://t.me/IliaAIToolsBot?start=devto-binance&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thread with live updates on X: &lt;a href="https://x.com/GhostWaynee/status/2115923817721954336" rel="noopener noreferrer"&gt;https://x.com/GhostWaynee/status/2115923817721954336&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>security</category>
      <category>blockchain</category>
      <category>web3</category>
    </item>
    <item>
      <title>AI Test Case Generator: Turn Requirements into TestRail-Ready Test Cases (Free Prompts)</title>
      <dc:creator>ILIA KARPENKO</dc:creator>
      <pubDate>Sun, 25 Oct 2026 04:23:34 +0000</pubDate>
      <link>https://dev.to/ghost_wayne/ai-test-case-generator-turn-requirements-into-testrail-ready-test-cases-free-prompts-2a6i</link>
      <guid>https://dev.to/ghost_wayne/ai-test-case-generator-turn-requirements-into-testrail-ready-test-cases-free-prompts-2a6i</guid>
      <description>&lt;p&gt;A new spec lands as a PDF on Monday. By Wednesday you have to hand over test cases in your team's TestRail format: their column names, their priority values, their ID scheme. You spend two days copying requirement text into rows, and the import fails anyway because one header reads &lt;code&gt;Expected Result&lt;/code&gt; instead of &lt;code&gt;Expected result&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So you paste the spec into ChatGPT or Claude and ask for test cases. You get rows of happy path, each with "Verify the feature works correctly" as the expected result, in columns nobody on your team uses.&lt;/p&gt;

&lt;p&gt;Your prompt skipped the work a QA lead does before writing a single case. This guide gives you that work as five prompts you can paste into any AI chat today. No tool to install.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Give the AI your format, not just the spec
&lt;/h2&gt;

&lt;p&gt;Attach two files: the requirements, and a file with two or three test cases your team already wrote. The example teaches the AI more than any description of your format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I'm attaching (1) the requirements for the Payments module and (2) three test
cases in my team's format.

Before anything else, describe the format of file 2: the exact column names in
order, the allowed values for Priority and Type, the ID scheme and the last ID
used, and the writing style of steps and expected results. Don't write any test
cases yet.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the answer. If it lists &lt;code&gt;High / Medium / Low&lt;/code&gt; and your team uses &lt;code&gt;Blocker / Critical / Major / Minor&lt;/code&gt;, correct it now. Every case inherits this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Ask for a plan and the gaps, not the cases
&lt;/h2&gt;

&lt;p&gt;This step decides what gets tested at all.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Read the requirements for the refund flow. Don't write test cases yet.

Give me:
1. A coverage plan: the areas you'll cover, the test design technique for each,
   and an estimated number of cases.
2. A list of gaps in the spec, each with the section number and one concrete
   question for the analyst. Look for: requirements with no measurable outcome,
   sections that contradict each other or a worked example, error paths that are
   never described, terms used as conditions but never defined, and external
   services whose failure is not specified.

End by asking me to approve or change the plan.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A spec that says "refunds should be processed quickly" has no testable outcome. A limit of $50,000 in one section and a worked example of a successful $75,000 refund in another is a contradiction someone has to resolve before you can write the boundary cases. "Silent on the error path" is the most common gap: the success flow fills a page, and nobody wrote what happens when the payment provider times out.&lt;/p&gt;

&lt;p&gt;Approve the plan, or cut it down. Then move on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Make the AI use real test design techniques
&lt;/h2&gt;

&lt;p&gt;Without explicit techniques, generated suites drift to whatever the spec mentions first: ten variations of the happy path. Name the techniques in the prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan approved. Write the test cases using:

- Equivalence partitioning: one case per group of inputs that behave the same.
- Boundary values on both sides of every edge. For a limit of 50,000 that means
  49,999, 50,000 and 50,001, not just the rejected value.
- A decision table wherever an outcome depends on several conditions: one case
  where all conditions pass, plus one case per condition failing on its own.
- State transitions: the allowed ones, and a case proving each forbidden one is
  rejected.
- Error guessing: empty and max-length input, double submit, session expiry
  mid-flow, network failure between request and response.

Use exactly the columns, values and ID scheme from step 1, continuing from the
last ID.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "both sides of every edge" line matters. A suite with 50,000 and 50,001 but no 49,999 proves the limit rejects. It never proves the system accepts everything up to the limit, so an off-by-one that moved the limit down would pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Review the cases against a quality bar
&lt;/h2&gt;

&lt;p&gt;Ask the AI to grade its own output before you read it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Review every case against these rules and fix the ones that fail:

1. Atomic: one behaviour per case. If the title needs "and", split it.
2. Independent: it sets up its own preconditions.
3. One deterministic expected result with values, e.g. "Balance decreases by
   $500 and the history shows a refund with status Completed". No "works
   correctly", no "either X or Y".
4. Concrete data in the steps: "Amount: 50,001", not "an amount over the limit".
5. Steps are actions; checks go in the expected result.
6. No two cases test the same partition.
7. Every requirement in scope has at least one case. List any that have none.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rule 3 protects the tester who runs the case. A case whose expected result reads "the operation ends in created or pending" can't be marked pass or fail. A real fork in behaviour means two cases. An undecided spec is a gap for the list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Export a file TestRail can import
&lt;/h2&gt;

&lt;p&gt;Ask for a CSV with your exact headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Export all cases as CSV. Use the headers from step 1, exactly as spelled, in the
same order. One row per case. Put each step on its own line inside the cell, not
as "&amp;lt;br&amp;gt;" or "\n" text. Quote every field.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two things break imports: a header that differs by one character from your field mapping, and multi-line steps that arrive as literal &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; tags. Open the file in a spreadsheet and check both before you import it into TestRail, Qase, Zephyr or Xray.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the prompts start to hurt
&lt;/h2&gt;

&lt;p&gt;The five prompts work. After a few sprints, these four things get old:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You re-describe your format every new chat, and the model forgets a column halfway through a long suite.&lt;/li&gt;
&lt;li&gt;It writes cases before you approve the plan unless you stop it every time.&lt;/li&gt;
&lt;li&gt;The gap list depends on how carefully you phrased step 2 that day.&lt;/li&gt;
&lt;li&gt;The CSV still needs a manual pass for headers and line breaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's why I packaged the workflow as &lt;strong&gt;&lt;a href="https://github.com/JohnWayneeee/casely-qa-skill" rel="noopener noreferrer"&gt;Casely&lt;/a&gt;&lt;/strong&gt;, a free, open-source skill for Claude Code, claude.ai, Cowork, the Claude desktop app and Codex. You attach the spec (or name a Jira issue or a Confluence page) and one example file, and say what you need:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Here are the requirements for the Payments module and two example test cases my team writes. Give me test cases for the refund flow."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Casely runs the five steps above in one conversation and stops once, at the plan, for your OK. It copies your columns, priority values and ID scheme from the example file. It writes the cases with the techniques from step 3, then exports one &lt;code&gt;.xlsx&lt;/code&gt; with your headers that TestRail imports in one pass, plus one Markdown file per case, or a UTF-8 CSV if your tracker wants one. Say yes once and it saves your team's style, so the next run needs no example file. When the spec describes an API, it also builds a Postman collection with every base URL, token and ID pulled out into variables, and no credentials in the file. When the spec names no endpoints, it asks for the API docs instead of inventing paths. In Claude Code, &lt;code&gt;/casely:run&lt;/code&gt; then walks the UI cases in a browser, and &lt;code&gt;/casely:bug&lt;/code&gt; turns a failure or a trace ID into a bug report in your team's format.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you know it finds the gaps?
&lt;/h2&gt;

&lt;p&gt;The repo ships a benchmark: a fintech wallet spec with &lt;strong&gt;five planted defects&lt;/strong&gt; (a vague "processed quickly", a $50,000 limit that contradicts a successful $75,000 example, a fee that is withheld but never sized, an undefined "verified status", and no behaviour for a payment provider outage), plus boundary rules, a state machine and a five-condition decision table. A 100-point rubric scores the run.&lt;/p&gt;

&lt;p&gt;The first full run scored &lt;strong&gt;85/100&lt;/strong&gt;. It produced 33 cases continuing the team's ID scheme, matched all nine columns in order, and exported one workbook with no rejected case. It missed two of the five planted gaps. The rules that catch those two are now part of the skill. The spec, the example file and the rubric are in &lt;a href="https://github.com/JohnWayneeee/casely-qa-skill/tree/main/benchmark" rel="noopener noreferrer"&gt;&lt;code&gt;benchmark/&lt;/code&gt;&lt;/a&gt;, so you can score a run yourself.&lt;/p&gt;

&lt;p&gt;Pick Opus for the plan phase if you can. Smaller models write acceptable cases from a plan they're handed, and miss the holes in the spec.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Is there a free AI test case generator?&lt;/strong&gt;&lt;br&gt;
The prompts in this article are free with any AI chat. Casely is free and open-source under the MIT license; you pay only for the Claude or Codex plan you already use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can I import AI-generated test cases into TestRail?&lt;/strong&gt;&lt;br&gt;
Yes. Match the headers to your TestRail field mapping exactly and keep multi-line steps as real line breaks. Casely exports a file that already does both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it work with requirements in other languages?&lt;/strong&gt;&lt;br&gt;
Casely writes the cases in the language of your example cases. A round-trip test checks that Arabic and Korean text, commas, quotes and line breaks survive the XLSX and CSV export cell for cell. A reader suggested the Korean case in the comments below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What about scanned PDFs?&lt;/strong&gt;&lt;br&gt;
Text-based PDFs, DOCX and XLSX work well. An image-only scan may not extract cleanly, so export a text version when you can.&lt;/p&gt;



&lt;p&gt;Add Casely to claude.ai, Cowork or the desktop app in one click from the &lt;a href="https://claude.ai/customize/plugins/id/8bcda77b-fec6-46f2-b329-ebca18a801c1%40anthropic-plugin-directory" rel="noopener noreferrer"&gt;Claude plugin directory&lt;/a&gt;. In Claude Code, paste this prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install the Casely plugin from https://github.com/JohnWayneeee/casely-qa-skill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Codex and manual setup are in the &lt;a href="https://github.com/JohnWayneeee/casely-qa-skill#install" rel="noopener noreferrer"&gt;README&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;More on how Casely came about: &lt;a href="https://medium.com/@ghost.waynee/your-qa-team-was-hired-to-find-bugs-it-spends-two-days-a-sprint-formatting-spreadsheets-a05d0a483821" rel="noopener noreferrer"&gt;Your QA team was hired to find bugs. It spends two days a sprint formatting spreadsheets&lt;/a&gt; and &lt;a href="https://medium.com/@ghost.waynee/stop-manually-writing-test-cases-how-i-built-a-claude-skill-that-turns-requirements-into-100-3d88a58ed283" rel="noopener noreferrer"&gt;Stop manually writing test cases&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If it saved you a day of formatting test cases, a ⭐ on the repo helps other QA engineers find it, and a &lt;a href="https://buymeacoffee.com/JohnWayne" rel="noopener noreferrer"&gt;coffee&lt;/a&gt; pays for the next release.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>qa</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How to Remove Ads from Google TV (and Make It Faster): a Free ADB Guide</title>
      <dc:creator>ILIA KARPENKO</dc:creator>
      <pubDate>Sun, 25 Oct 2026 04:09:55 +0000</pubDate>
      <link>https://dev.to/ghost_wayne/how-to-remove-ads-from-google-tv-and-make-it-faster-a-free-adb-guide-592f</link>
      <guid>https://dev.to/ghost_wayne/how-to-remove-ads-from-google-tv-and-make-it-faster-a-free-adb-guide-592f</guid>
      <description>&lt;p&gt;&lt;em&gt;No root. Every step can be undone. The full command list, the two traps that turn a TV into a black screen, and how to stop the TV from watching what you watch.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You turn the TV on to watch one thing. First you get a row of ads and "recommended for you". The menu lags a second behind the remote. Apps open slowly. You search for a fix and find forum threads with a list of &lt;code&gt;adb&lt;/code&gt; commands, no explanation, and no way back if one of them kills your Wi-Fi.&lt;/p&gt;

&lt;p&gt;This guide shows how to remove ads from the Google TV home screen, free memory and switch off screen tracking using ADB, step by step, with the undo command for each change. You need a computer and the TV on the same network.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your TV shows ads and slows down
&lt;/h2&gt;

&lt;p&gt;Out of the box an Android TV or Google TV set runs a dozen vendor services in the background: telemetry, content stores, recommendation rows, a second cast receiver, a demo mode. The home screen itself is an ad surface. All of it shares 1–3 GB of RAM with the apps you open.&lt;/p&gt;

&lt;p&gt;The picture and sound get the same treatment. Motion smoothing, noise reduction and "enhancers" are on by default. On one CHiQ set I tuned, the stock equaliser boosted 5 kHz by +41.&lt;/p&gt;

&lt;p&gt;There is also a part you don't see. Most smart TVs run ACR, automatic content recognition. The TV samples what is on screen several times a second, films from an HDMI box or a console included, matches it against a database and sends the result for ad targeting. A 2024 UC Davis / UCL study measured Samsung sampling every 500 ms and LG every 10 ms. On Android TV and Google TV it is usually Samba TV (Sony, TCL, Philips and others) or the vendor's own service. Vendor apps can also hold the microphone and the camera.&lt;/p&gt;

&lt;p&gt;That is a large part of why TVs keep getting cheaper: the money is in the viewing data. In December 2025 Texas sued Samsung, Sony, LG, Hisense and TCL over ACR. Step 6 switches it off and checks that it is really off.&lt;/p&gt;

&lt;h2&gt;
  
  
  The quick fix, and why it isn't enough
&lt;/h2&gt;

&lt;p&gt;Google TV has an &lt;strong&gt;Apps-only mode&lt;/strong&gt; (Settings → Accounts &amp;amp; Sign In → your account → Apps only mode). It hides most recommendations. The stock home screen stays, the vendor services keep running, and the lag stays with them.&lt;/p&gt;

&lt;p&gt;An ad-blocking DNS (Settings → Network → Private DNS, for example &lt;code&gt;dns.adguard-dns.com&lt;/code&gt;) blocks some ad requests on Android 9 and newer. It does not block YouTube ads.&lt;/p&gt;

&lt;p&gt;To fix the cause you have to switch off the services themselves. That takes ADB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Turn on developer options and debugging
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Open &lt;strong&gt;Settings → System → About&lt;/strong&gt; (on older Android TV: &lt;strong&gt;Settings → Device Preferences → About&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Press OK on &lt;strong&gt;Build&lt;/strong&gt; (or &lt;strong&gt;Android TV OS build&lt;/strong&gt;) seven times. You'll see "You are now a developer".&lt;/li&gt;
&lt;li&gt;Go back to &lt;strong&gt;Developer options&lt;/strong&gt;. Turn on &lt;strong&gt;USB debugging&lt;/strong&gt;, and &lt;strong&gt;Network debugging&lt;/strong&gt; if it is listed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;On a computer, install Android SDK platform-tools, which contain &lt;code&gt;adb&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Connect over the network
&lt;/h2&gt;

&lt;p&gt;Find the TV's IP address in &lt;strong&gt;Settings → Network&lt;/strong&gt;. Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb connect 192.168.1.50:5555
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A prompt "Allow USB debugging?" appears on the TV. Tick &lt;strong&gt;Always allow from this computer&lt;/strong&gt; and press OK. Without the tick, the prompt comes back every time you reconnect.&lt;/p&gt;

&lt;p&gt;If the connection is refused, your TV may only offer &lt;strong&gt;Wireless debugging&lt;/strong&gt; (common on Google TV 12+). Open it, choose &lt;strong&gt;Pair device with pairing code&lt;/strong&gt;, then on the computer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb pair 192.168.1.50:&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;pairing-port&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;     &lt;span class="c"&gt;# enter the code shown on the TV&lt;/span&gt;
adb connect 192.168.1.50:&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;port-shown-on-tv&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
adb tcpip 5555
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If nothing answers at all, not even your router, a VPN on the computer is capturing the local network. Exclude your home subnet from the tunnel.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Save what you have before changing anything
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm list packages -s &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; packages-system.txt
adb shell pm list packages -3 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; packages-3rdparty.txt
adb shell pm list packages -d &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; disabled-before.txt
adb shell &lt;span class="s2"&gt;"grep -E 'MemTotal|MemAvailable' /proc/meminfo"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write down &lt;code&gt;MemAvailable&lt;/code&gt;. You'll compare it at the end.&lt;/p&gt;

&lt;p&gt;Now the first trap. Check which app owns your saved Wi-Fi network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell &lt;span class="s2"&gt;"dumpsys wifi | grep -o 'cname=[^ ]*'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you disable the app that saved a network, Android deletes that network. The TV drops off Wi-Fi, and your ADB session drops with it. Never disable the package this command names. On Google TV it is often the setup wizard, and that matters in step 7.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Decide what to disable
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;packages-system.txt&lt;/code&gt; and sort the vendor packages into groups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vendor telemetry and analytics;&lt;/li&gt;
&lt;li&gt;vendor stores, recommendation rows and content providers;&lt;/li&gt;
&lt;li&gt;background services you don't use: a second cast receiver, cleaners, demo modes, print;&lt;/li&gt;
&lt;li&gt;preinstalled apps you never open.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When a package name says nothing, read it without starting it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell &lt;span class="s2"&gt;"dumpsys package &amp;lt;package&amp;gt; | grep -E 'versionName|sharedUser|permission\.'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;BIND_TV_INPUT&lt;/code&gt; means an input or remote service: keep it. Firebase or &lt;code&gt;c2dm&lt;/code&gt; together with a boot receiver usually means push and telemetry.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Never disable these.&lt;/strong&gt; Each one can stop the TV from booting, showing a picture or taking input:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Android core: &lt;code&gt;android&lt;/code&gt;, &lt;code&gt;com.android.systemui&lt;/code&gt;, &lt;code&gt;com.android.shell&lt;/code&gt;, &lt;code&gt;com.android.settings&lt;/code&gt;, &lt;code&gt;com.android.tv.settings&lt;/code&gt;, the permission controller, the package installer, and &lt;code&gt;com.android.providers.*&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;What the TV needs to work: the TV app and HDMI/tuner input services, the input menu, &lt;code&gt;com.android.bluetooth&lt;/code&gt; and the remote pairing service, the on-screen keyboard, Play Store, Play Services, the Android TV Remote service.&lt;/li&gt;
&lt;li&gt;Any package with &lt;code&gt;factory&lt;/code&gt;, &lt;code&gt;fac&lt;/code&gt; or &lt;code&gt;AT&lt;/code&gt; in its name. Don't disable them, and don't even open them. On some Haier and CVTE boards, opening one flips a factory flag: the Input key and HDMI-CEC stop working, and the next boot disables Play Services.&lt;/li&gt;
&lt;li&gt;The Wi-Fi owner from step 3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An original Mi TV Stick never booted again after a debloat list took six of the core packages. Check each package yourself instead of trusting a list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Disable in small batches
&lt;/h2&gt;

&lt;p&gt;Disable, don't uninstall. &lt;code&gt;disable-user&lt;/code&gt; is reversible. &lt;code&gt;uninstall&lt;/code&gt; on a system package is much harder to undo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm disable-user --user 0 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do four or five packages at a time. After each batch, press Home on the TV and check that the picture, the remote and the network still work. If something breaks, you know which batch did it.&lt;/p&gt;

&lt;p&gt;Check the result by listing, not by the exit code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm list packages -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some firmware (Fire OS and a few others) prints success and changes nothing, or refuses with &lt;code&gt;SecurityException&lt;/code&gt;. If every package is refused, your TV doesn't allow this. Use the TV's own privacy toggles (step 6) and the DNS from above instead.&lt;/p&gt;

&lt;p&gt;Undo one package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6. Stop the TV from watching you
&lt;/h2&gt;

&lt;p&gt;Do this even if you only came for the clean home screen. It takes ten minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Switch it off in the menu.&lt;/strong&gt; Paths differ by model and year, so look around Settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sony, Philips, TCL and other Android TV sets: &lt;strong&gt;Samba Interactive TV&lt;/strong&gt;, &lt;strong&gt;Interactive TV&lt;/strong&gt; or &lt;strong&gt;Viewing information&lt;/strong&gt; → off. It sits under Settings → Privacy, Device Preferences or Initial setup.&lt;/li&gt;
&lt;li&gt;Google TV and Android TV 12+: &lt;strong&gt;Settings → Privacy → Usage &amp;amp; Diagnostics&lt;/strong&gt; → off. &lt;strong&gt;Settings → Privacy → Ads → Delete advertising ID&lt;/strong&gt; (older builds: &lt;strong&gt;Opt out of Ads Personalization&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;The vendor's own privacy screen: anything called viewing information, content recognition, user experience programme or personalised recommendations → off.&lt;/li&gt;
&lt;li&gt;If you never talk to the TV, switch off &lt;strong&gt;"Hey Google"&lt;/strong&gt; / hands-free voice. Some sets have a physical mic switch on the edge.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A switch is a promise, not proof. Check for yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Find the tracking packages:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm list packages &lt;span class="o"&gt;|&lt;/span&gt; grep -iE &lt;span class="s2"&gt;"samba|acr|alphonso|inscape|gracenote|nielsen|interactive|viewing|ads|analytic|telemetry|bigdata"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a lead, not a verdict: &lt;code&gt;ads&lt;/code&gt; also matches harmless names. Read each one with the &lt;code&gt;dumpsys&lt;/code&gt; command from step 4, then disable the ones you are sure about the same way as in step 5, and play one video after it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;See who holds the microphone and the camera:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell dumpsys package packages &lt;span class="o"&gt;|&lt;/span&gt; grep -E &lt;span class="s2"&gt;"Package \[|RECORD_AUDIO: granted=true|CAMERA: granted=true"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; grep -B1 &lt;span class="s2"&gt;"granted=true"&lt;/span&gt;
adb shell pm list features &lt;span class="o"&gt;|&lt;/span&gt; grep -iE &lt;span class="s2"&gt;"microphone|camera"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first command lists apps that may use the mic or the camera. The second shows whether the TV has them at all. Block both for every app you don't use them with. Keep the mic for the voice assistant if you press the mic button on the remote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell cmd appops &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; RECORD_AUDIO ignore
adb shell cmd appops &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; CAMERA ignore
adb shell cmd appops get &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; RECORD_AUDIO     &lt;span class="c"&gt;# check: ignore&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Undo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell cmd appops &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; RECORD_AUDIO default
adb shell cmd appops &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; CAMERA default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This survives a reboot. If the TV has a pop-up or clip-on camera, push it down or cover it too: software can't prove a camera is off, a shutter can.&lt;/p&gt;

&lt;p&gt;The ad-blocking Private DNS from the start of this guide also cuts many tracking hosts that no package list catches.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7. Replace the ad-filled home screen
&lt;/h2&gt;

&lt;p&gt;Install a launcher first. Any Android TV launcher works for this step. Then try to make it the Home app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell cmd package set-home-activity &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;launcher.package&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;/&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;.MainActivity&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On most Google TV sets this prints &lt;code&gt;Success&lt;/code&gt; and changes nothing. The stock launcher, &lt;code&gt;com.google.android.apps.tv.launcherx&lt;/code&gt;, has Home priority 2. The setup wizard's &lt;code&gt;RecoveryActivity&lt;/code&gt; has priority 1. A third-party launcher is capped at priority 0. The system picks the highest priority, whatever you set as preferred.&lt;/p&gt;

&lt;p&gt;So you have to disable the stock launcher, and that hides the second trap. If you disable only &lt;code&gt;launcherx&lt;/code&gt;, the setup wizard's &lt;code&gt;RecoveryActivity&lt;/code&gt; takes over Home, tries to re-enable &lt;code&gt;launcherx&lt;/code&gt;, fails, and loops on a black screen. You have to disable the wizard too, &lt;code&gt;com.google.android.tungsten.setupwraith&lt;/code&gt;. The wizard often owns the Wi-Fi network from first setup. Do it in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the Wi-Fi check from step 3. If it names &lt;code&gt;setupwraith&lt;/code&gt;, go to &lt;strong&gt;Settings → Network&lt;/strong&gt;, &lt;strong&gt;forget&lt;/strong&gt; your network and join it again. The TV may get a new IP: reconnect ADB.&lt;/li&gt;
&lt;li&gt;Run the check again. The owner should now be &lt;code&gt;com.android.tv.settings&lt;/code&gt; or a system uid.&lt;/li&gt;
&lt;li&gt;Disable both:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm disable-user --user 0 com.google.android.tungsten.setupwraith
adb shell pm disable-user --user 0 com.google.android.apps.tv.launcherx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Press Home and check who holds the screen:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell &lt;span class="s2"&gt;"dumpsys activity activities | grep mFocusedApp"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see a black screen at any point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell pm &lt;span class="nb"&gt;enable&lt;/span&gt; com.google.android.apps.tv.launcherx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then press Home.&lt;/p&gt;

&lt;p&gt;One cost to know about: on Google TV the stock launcher also handles the gear (dashboard) button on the remote. After the swap that button stops working, and no third-party app can take it over. The Input button keeps working.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8. Make it faster
&lt;/h2&gt;

&lt;p&gt;Halve the animations so menus respond quicker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell settings put global window_animation_scale 0.5
adb shell settings put global transition_animation_scale 0.5
adb shell settings put global animator_duration_scale 0.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stop background Wi-Fi and Bluetooth scanning, which a TV doesn't need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell settings put global wifi_scan_always_enabled 0
adb shell settings put global ble_scan_always_enabled 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On Android 11 and newer, freeze cached apps so they use no CPU in the background (reboot to apply):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell settings put global cached_apps_freezer enabled
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before you change a setting, read its old value with &lt;code&gt;settings get global &amp;lt;key&amp;gt;&lt;/code&gt; and write it down. That is your undo.&lt;/p&gt;

&lt;p&gt;Now measure &lt;code&gt;MemAvailable&lt;/code&gt; again and compare it with step 3.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9. Turn off the picture "enhancers"
&lt;/h2&gt;

&lt;p&gt;Open the picture menu (on Google TV: &lt;strong&gt;Settings → Display &amp;amp; Sound → Picture&lt;/strong&gt;) and switch off motion smoothing, noise reduction and dynamic contrast. Pick a Movie or Cinema mode with a warm colour temperature. Picture settings are usually per input, so repeat this for each HDMI port you use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 10. Close the door behind you
&lt;/h2&gt;

&lt;p&gt;Network debugging on port 5555 is plaintext and gives a shell to any authorised computer on your network. When you're done:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In &lt;strong&gt;Developer options&lt;/strong&gt;, switch off USB debugging and network debugging.&lt;/li&gt;
&lt;li&gt;Tap &lt;strong&gt;Revoke USB debugging authorisations&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Reboot the TV.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why I stopped doing this by hand
&lt;/h2&gt;

&lt;p&gt;I've done the steps above on several TVs. Five things kept slowing me down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vendor package names say nothing. Every brand calls its telemetry something different, and you have to read each one.&lt;/li&gt;
&lt;li&gt;The Wi-Fi owner trap and the setup wizard loop give no warning. You learn about them from a black screen.&lt;/li&gt;
&lt;li&gt;Factory packages differ by board, and one wrong tap can break the Input key for good.&lt;/li&gt;
&lt;li&gt;The tracking switches are buried in different menus on every brand, and nothing tells you whether they actually worked.&lt;/li&gt;
&lt;li&gt;To undo everything you need a log of every package and every setting you changed, with the old values.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I wrote &lt;strong&gt;&lt;a href="https://github.com/JohnWayneeee/cleantv" rel="noopener noreferrer"&gt;CleanTV&lt;/a&gt;&lt;/strong&gt;, a free, open-source skill for Claude Code. You turn on debugging and say "Set up my TV". It does the steps in this article on your real TV:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You&lt;/strong&gt; turn on debugging, say "Set up my TV" and answer 10–15 questions about how you use the TV.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude&lt;/strong&gt; finds the TV on your network, picks the packages, runs every &lt;code&gt;adb&lt;/code&gt; command, and checks each step with a screenshot from the TV.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It backs up the TV before the first change. It refuses core, factory and Wi-Fi owner packages. It finds the ACR and ad packages, walks you through the tracking switches with a screenshot check, and takes the microphone and the camera away from vendor apps. It disables the stock launcher and the wizard in the right order. It installs its own launcher: a pitch-black home screen with a dock of your apps, a clock and an HDMI inputs menu. It calibrates picture and sound for your room, and at the end it closes network debugging and checks that the port is shut. One command, &lt;code&gt;restore.py&lt;/code&gt;, undoes all of it.&lt;/p&gt;

&lt;p&gt;Measured on two TVs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;CHiQ, 2.8 GB RAM:&lt;/strong&gt; free memory went from 1.42 GB to &lt;strong&gt;1.77 GB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harper, 1.8 GB RAM:&lt;/strong&gt; free memory went from 721 MB to &lt;strong&gt;888 MB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Home screen:&lt;/strong&gt; ads and recommendations replaced by &lt;strong&gt;your apps on black&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Screen tracking:&lt;/strong&gt; ACR off, &lt;strong&gt;microphone and camera locked&lt;/strong&gt; for vendor apps.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It works on Android TV and Google TV: Xiaomi, TCL, Hisense, Sony, Philips, CHiQ/Changhong, Haier, Harper, Nvidia Shield and others. It doesn't work on Samsung Tizen, LG webOS or Fire TV.&lt;/p&gt;

&lt;h2&gt;
  
  
  If YouTube is throttled where you live
&lt;/h2&gt;

&lt;p&gt;In some countries, Russia among them, the ISP slows YouTube down with deep packet inspection. Videos stall while everything else works.&lt;/p&gt;

&lt;p&gt;CleanTV can install &lt;a href="https://github.com/romanvht/ByeByeDPI" rel="noopener noreferrer"&gt;ByeByeDPI&lt;/a&gt;, an open-source app, on the TV itself. It runs locally as a VPN: no external server, no account. Only YouTube's traffic goes through it, every other app keeps the direct route. The CleanTV launcher starts the bypass when you open YouTube and stops it when you return Home.&lt;/p&gt;

&lt;p&gt;To set it up by hand: install the APK for your TV's CPU (&lt;code&gt;adb shell getprop ro.product.cpu.abi&lt;/code&gt;), set the DNS to Google (8.8.8.8), turn on the app whitelist with only &lt;code&gt;com.google.android.youtube.tv&lt;/code&gt;, and run the built-in strategy test. The test takes 10–15 minutes; don't touch the remote while it runs.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Can you remove ads from Google TV without root?&lt;/strong&gt;&lt;br&gt;
Yes. Everything in this guide works over ADB debugging, which you turn on in Developer options. No root, no unlocked bootloader.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is it safe?&lt;/strong&gt;&lt;br&gt;
Disabling is reversible: &lt;code&gt;pm enable &amp;lt;package&amp;gt;&lt;/code&gt; brings a package back. The risk is in what you disable. Stick to the never-disable list in step 4, work in small batches, and check the Wi-Fi owner first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will it remove YouTube ads?&lt;/strong&gt;&lt;br&gt;
No. This removes ads from the home screen and switches off vendor services. YouTube serves its own ads, and neither a launcher nor DNS can remove them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does my TV really watch what I watch?&lt;/strong&gt;&lt;br&gt;
If ACR is on, yes. It recognises the picture, also from HDMI, and reports it for ads. Step 6 switches it off, disables the tracking packages and locks the mic and camera.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I have a Samsung or LG. Can I at least turn the tracking off?&lt;/strong&gt;&lt;br&gt;
ADB won't help on Tizen or webOS, but the switches are in the menu. Samsung: Settings → Support → Terms &amp;amp; Privacy → Viewing Information Services off, and Interest-Based Advertisement off. LG: Settings → General → System → Additional Settings → Live Plus off, and in User Agreements untick Viewing Information and Interest-Based Recommendation. Paths change by model year.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Does it work on Fire TV?&lt;/strong&gt;&lt;br&gt;
No. Fire OS refuses &lt;code&gt;pm disable-user&lt;/code&gt;, and Fire TV doesn't use the Google TV launcher.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Will a system update undo it?&lt;/strong&gt;&lt;br&gt;
Some firmware re-enables its own packages on every boot (TCL on Android 9 does this). After a reboot, compare &lt;code&gt;pm list packages -d&lt;/code&gt; with your list.&lt;/p&gt;




&lt;p&gt;If you'd rather not spend the evening on it, &lt;strong&gt;&lt;a href="https://github.com/JohnWayneeee/cleantv" rel="noopener noreferrer"&gt;CleanTV is on GitHub&lt;/a&gt;&lt;/strong&gt;. Install it in Claude Code and say "Set up my TV".&lt;/p&gt;

&lt;p&gt;If it saved you that evening, a ⭐ on the repo helps other owners find it, and a &lt;a href="https://www.buymeacoffee.com/JohnWayne" rel="noopener noreferrer"&gt;coffee&lt;/a&gt; pays for the next module: remote buttons and Bluetooth remotes.&lt;/p&gt;

</description>
      <category>android</category>
      <category>adb</category>
      <category>tutorial</category>
      <category>privacy</category>
    </item>
  </channel>
</rss>
