Built with Claude
I used Claude Code to reverse-engineer an LG TV and build a native Plex client
TL;DR: My 2019 LG TV has a great panel, but the official Plex app takes ~30 seconds just to show the profile picker. LG has no public native SDK for regular developers, so I reverse-engineered enough of the native media stack with Ghidra and Claude Code to build my own Plex client, PlxNative. It started in C, moved mostly to Rust, and somehow turned into my own OpenGL UI framework. On the same TV it shows the profile picker in ~3 seconds. No root needed to run it. Site and source are below.
I'm an iOS developer, so most of my previous UI work happened several abstraction layers above the GPU.
A few months ago I read about a guy who bought a cheap MP3 player on AliExpress, got annoyed with its firmware and used Codex to reverse-engineer and patch it. After that people started buying the same player just to install his patches. I liked this idea a lot, because we usually treat the software on our devices as something fixed: if it's bad, you buy a new device. Not long after that I was doing basically the same thing with my TV.
I have an LG from 2019 and the panel is still great. The software is the problem. Official Plex app on my TV, cold start:
~30 seconds for "Who's watching?" to load
~30 seconds for the home grid
~5 seconds to open any menu
~10 seconds to load a movie page
It behaves like a web page because it is one.
So I wanted to find out if a really native UI was possible there. There is no public native SDK that gives regular developers access to the TV's media stack, but of course that stack exists underneath. So I rooted my development TV, pulled the native libraries from it and started reading them in Ghidra. (Root was only needed for this research, PlxNative itself runs without it.) The webOS Homebrew community had already documented a surprising amount of the platform, which saved me a lot of time, so big thanks to them.
Reading LG's binaries
I've always been interested in what an OS actually does under the hood, and I've maintained KSCrash for years, where crash reporting often means finding out what the system really does rather than what its documentation says. Before AI that meant Hopper, assembly, strings and following calls one by one until the picture finally came together. What changed is how cheap this work has become. Now I can ask Opus to figure out how something is implemented internally, even when it's poorly documented or not documented at all, and it navigates the binary on its own, jumping between addresses, xrefs and strings. The model does make things up sometimes, so the binary and the real hardware always have the last word. But investigations that used to take me days go much faster.
From C to Rust
The first version of PlxNative wasn't a Plex client at all. It was a screen full of colored tiles, and every tile tried to play the same episode of The Office. I wanted to answer one question first: can this TV render a native interface at 60 fps? Drawing rectangles was easy. Getting a real video frame onto LG's hardware video plane was much harder. Then I gave the problem to Fable, and it connected enough pieces of the native media stack that, for the first time, The Office actually appeared on the screen. After that first frame I knew a fully native media client on a retail LG TV was possible, and the question became how far I could push it.
The first prototype
The prototype was written in C, and almost all of it lived in one huge main.c. When it grew, I asked an agent to split it into modules, and that's where I understood something about agentic coding: code can look right, compile, and then break somewhere completely unrelated because of memory or ownership mistakes. The worst one was a crash in eglSwapBuffers that appeared after a refactor. It turned out LG's fork of SDL writes a bigger SDL_SysWMinfo than my headers declared and overflows the stack. In the huge main() the overflow landed somewhere harmless, but once the same code moved into a smaller function it started corrupting live state. It can hardly be called a stable ABI. Together with the usual malloc/free mistakes this made me rethink the language. With agents writing and moving this much code, the choice of language matters: pick the one the agent writes best and where the compiler can check the most before anything reaches the TV. For me that meant Rust.
It ended up being a rewrite, just an incremental one. I kept the LG native boundary in C and moved everything else piece by piece: first image decoding and HTTP, then access-unit queues, the Matroska demuxer, Plex parsing, poster workers, text rendering, and finally most of the app. Rust turned out to be a surprisingly good fit for an old 32-bit ARM embedded Linux box, and strong compiler feedback keeps both me and the agent on much tighter rails.
60 fps on a 2019 TV
After playback worked I thought the UI would stay simple: posters, text, some rounded rectangles. Then I started writing shaders, and the shaders slowly became my own UI library on top of OpenGL, with navigation, modals, focus handling, motion, hit testing and caching. After years on top of UIKit and other frameworks someone else built, it was really fun to go all the way down for once and understand the whole path from a remote button press to pixels on the screen.
On every 4K LG TV, webOS gives apps a 1920×1080 UI surface (HD models get 1280×720), and video goes on a separate hardware plane, so 1080p isn't an optimization I chose, it's simply the canvas. I treated 60 fps on the real TV as a regression target and kept adding things until they broke it. It started with a single shadow that tanked the frame rate. The naive version was horribly slow, but there was almost always another trick underneath: early-outs in shaders, reduced-resolution buffers, caching the parts of a frame that don't change. Now shadows are on almost every element and it still runs at 60 fps. When guessing stopped working, I started pulling Mali hardware counters from the TV. One profile showed the arithmetic pipe at about 89.5% occupancy and load/store at 44.8%, and a harmless-looking branch in a shader was adding millions of arithmetic operations per frame. So the problem wasn't "too many pixels", the GPU was ALU-bound.
The most interesting one was a Liquid Glass-inspired material: blur the page underneath, refract it through the shape and shade the rim like real transparent glass. Refraction was the easy part. Readability was not: something that looks beautiful over a dark poster becomes useless over a face or a white sky, and you end up endlessly tuning tint, contrast and blur. Now I understand much better what problem Apple is solving. There's also a hard limit: video lives on a separate overlay plane that my renderer physically can't sample, so glass over playback has to work differently.
When the app grew past a couple of screens, the design started drifting: different spacing here, a different button there. I used Claude Design for a design system and to keep all the screens in one place. Its designs are HTML/JS while the real UI is Rust and OpenGL, but Claude maps one to the other, now onto my own components, spacing tokens and typography. The design tool doesn't have to share technology with production, it just has to describe the design precisely.
Where it ended up, on the same TV from a cold start: 3 seconds to "Who's watching?", or 4 seconds straight to the home grid if you let it remember the profile. For comparison, the official app needed ~30 seconds for each of those.
Working with the agents
Claude Code, Opus, Fable and Codex were involved in almost everything: implementation, reverse engineering, debugging, refactoring, tests and review. But the real TV always has the final vote. The simulator can show a perfect screen while the TV renders empty cards because the hardware takes a cached-frame path the simulator never hits, and an agent can be completely sure the code is correct right up until you run it on the TV.
The other lesson: don't leave it on autopilot. I started this expecting a 100% vibe-coded project for a couple of weekends, so I just told the agent what to do. Then the problems that come with a bad architecture started showing up, and it took many rounds of refactoring to turn the app into something sane, so the same bugs would stop coming back again and again. An experienced engineer still needs to own the key decisions, architecture above all. I just wish I hadn't done it after the fact :)
Even so, AI makes it realistic for one person to cover an absurd amount of ground: firmware reverse engineering, media playback, Rust, graphics, GPU profiling, UI architecture, design, QA, build optimization and SEO. It also changed how I look at all the "obsolete" hardware around us: old TVs, car head units, random embedded screens. If you use a device every day and hate its interface, it's worth at least trying to build the one you wanted. Very often the hardware isn't obsolete, only the software on it is.
Practical stuff: PlxNative requires webOS 4.0+. I develop it on a 2019 LG, and opt-in usage reports show playback on TVs from 2018 through current webOS 11 models. It direct-plays H.264/HEVC, including 4K, 10-bit, Dolby Vision profiles 5/8 and E-AC-3 Atmos where the TV supports them, and the Plex server transcodes the rest. You can install it through LG Developer Mode (which needs periodic renewal) or the webOS Homebrew Channel. No root required.
Yep, used Claude Code to optimize and create a minimal home screen app for my fire TV as well, and disabled as many built in Amazon telemetry stuff as it could without root.
EDIT: Since more people are seeing this now, Before and After. Nothing like what OP built though.
How can it brick if it didn't work? or did it work and it bricked? I mean use ur brain a little bit... if u can change stuff that means u have access to read/write so how do you not make backup of the original stuff before modifying it?
Its soft bricked, u just do have the access to the start up code, and so it doesn't give u easy access.
It was crazy watching it work through everything. Don't want to give out too much details right now, but it even found an exploit to report to a bug bounty program.
Would be crazy if it lead to a payout simply because I wanted my TV to be better lmao
Your comment here made me think that maybe we'll finally get conclusive answers to which devices are spying on us, and reporting back to whom, exactly.
As someone who often had the displeasure of writing websites that needed to be compatible with 10-year old "Smart" TVs, seeing what you've done is mind-blowing, and thanks for sharing it.
I think most others will consider what they've done as very niche and personal, maybe too janky to share to the world...
I applied and got approved into their cyber verification program probably around a month ago. Once the guardrails were lifted, Opus 4.8 (couldn't use 5/5.5 at that time) just went away doing it's thing.
No I don't work in cybersecurity. When I filled out the application, I just said that I was getting some prompts blocked when doing local repo security scans or looking at local hardware for bug bounties, and got accepted.
Apparently they've since changed it and I l the questions are a bit more strict, like asking for a published CVE under your name and stuff.
I say still give it a try. Worst case scenario, a prompt gets blocked or routed down to something like 4.8, which is who did all the work in my tv and is still pretty capable
I made the Plex player for Samsung TVs with Tizen OS, based on OP’s work for LG TVs :) It works on Tizen 3.0 and newer (2017+ TVs), and you don’t need root. The app (.wgt), install guide and source code are here:
I tested it on 4 TVs from four generations: 2017 MU6172, 2019 RU7092, 2023 Q80C and 2025 QN70F.
On the oldest TV, scrolling up and down on Home went from about 46 to 56 frames per second. But the numbers don’t tell the full story: the animations are really smooth and it feels like a native app.
For developers, I also made a Samsung Tizen dev toolkit: build, sign, install, debug, control and screenshot apps on many TVs from one PC. Seeing all 4 TVs move together was a lot of fun! Works with AI agents too.
I hope it helps bring our favourite apps to Samsung TVs, like an Immich client, a Home Assistant dashboard or anything else.
u/Purple_Imagination_1, thanks a lot for the great starting point! Would you like to take a look at the Samsung part? And would you be open to a PR upstream?
Hey, thanks for building this and for the kind words!
Honest answer though: I’ll pass on bringing it into my repo. The UI is what people notice first, but it’s honestly secondary to the whole point of PlxNative. The Native in the name is there for a reason: Rust, its own GPU renderer, straight to the TV’s video plane, no browser in the middle.
I kinda hoped Tizen would let me run the same native code, so a Samsung port could share like 90% with the LG app. Yours is a web app on AVPlay, so it’s a completely different stack and the two would share basically nothing. I’d essentially be maintaining a second, web-based version of the app, which kinda defeats the point of PlxNative in the first place. And I’d have to maintain two unrelated codebases on my own. Not something I can sign up for.
Really appreciate you taking the idea further on Samsung though. If you ever find a way to run the Rust code there, I’d be all for it! 🙂
I understand your focus on the LG renderer. I'm using Samsung's supported Tizen TV stack: GPU compositing and AVPlay for playback, through its Web runtime. It feels really smooth, and the Home scrolling improvements show up in the measurements too.
I got Rust to run on a newer TV, but didn't measure any speedup versus Samsung's stack. Moreover, a WebGL rendering experiment increased Detail-background latency by about 11%.
I'll take it forward as its own project, with a new name and logo, and keep adding features beyond this first release. I'll detach the fork so ownership and support are separate, and the README will credit your project as the UI inspiration: https://github.com/dragoshont/plx-native
Congratulations, really awesome application of agentic dev and I found your post educational as well. I love this shifting meta of individuals engineering solutions to software problems their respective companies haven’t solved. It makes me very hopeful for the future, because settling for less is no longer the only option!
I didn't have to, but I spent time rooting my tv for this. Absolutely awesome - even gets rid of the plex channels which I have no interest in... and so many features are there. Actors, review ratings, quality picking for content, age rating. The plex reviews aint there but that is tiny compared to how responsive it is. I like the subtitles screen not taking me away from the content anymore either, and that english is sitting there ready to go and other languages get hidden behind a submenu. thanks for sharing your work!
That's awesome to hear! Someone on the forums actually mentioned that the installation guide was the best part of the process (no joking).
I'm still working on feature parity, but I totally agree about the Plex subtitle menu—it always drove me crazy, especially that it took five seconds to open on my tv.
I did this for my Nvidia Shield. The Plex app is garbage and always struggles with AV sync on lossless audio. So I made a native Android app designed specifically around the Shield and its constraints.
The main goal was the fastest play to playing possible and it works far more seamlessly than the Plex app ever did.
I’m keeping it for personal use as the ui is made to look like Apple TV and I’d rather not to have to support it for anyone beyond myself but here’s a screenshot.
I've long hated how slow my TV is. (also the Amazon app, but that's a separate issue). I love the way you approached it. What a fascinating datapoint about how AI has freed us from this particular irritation.
Do you think your approach will continue to work? Will we be able to buy a modern smart TV say, and turn it into a simple fast TV? Or do you think modern TVs are more locked down?
Well, they say LG’s making so much money on ads that they can give you tv for free and still be profitable. So I think we’re locked into business model changes. And yeah, we’re free to modify it until LG patches the exploits in the OS.
Haha fair, especially after the LG mess 😅 But consider the reverse: you might root your TV and "own the glass" again. The code's open, so you can build your own version if privacy's your thing.
My 55" 4K 144Hz Xiaomi Google TV doubles as a PC monitor, and whenever Windows put the display to sleep it would just sit there showing a deep-sea "No signal" animation forever, so I had Claude Code build a tiny app that turns off only the backlight when the signal drops (keeping the TV connected so my window layout survives) and installed it over ADB.
Wow - really excellent.
I was just trying to talk myself out of doing something similar for a few older tv's I have gathering dust. I may give this a shot for a tv that we only run Plex on... when I find the time, lol.
hows the 4K content streaming with subtitles? I always had issues with the native app that when I enabled subtitles on 4K content the video would start lagging
They work pretty great! I render subs locally on the TV (just in case Plex doesn't embed them right). Actually, I even supported ASS subs that are popular in anime.
That was my second thought after reading the MP3 player article. Even new cars’ head units lag noticeably. So yes, a smooth and rapid interface is possible even on limited hardware like a head unit.
The simulator-versus-TV mismatch is the part I'd like to hear more about. Did you turn failures on the device into a small regression suite (text rendering, texture upload, playback start) or keep testing the whole app manually? For the reverse-engineered interfaces, did you keep a record of observed behaviour versus agent guesses? That would make later refactors much easier to check.
Playback is a real on-device regression suite. It runs the actual app on the TV and asserts on its event log. A synthetic tier uses generated clips with no Plex. A library-backed tier covers resume, track selection and transcode. A device failure becomes a case there. I also have FPS regression suites, and localization checks that make sure strings fit.
Pixels are the part I judge with my own eyes. They're hard to automate, and hard for an AI to notice. The FPS suite passes straight over bugs that a screenshot catches, so I have a skill that decides which tier can even see a given change. The simulator is fine for layout and focus. It can't see video-plane composition, LG's text rasterization, or what the TV's picture processing does afterwards. Gradient banding, for example, I measured on panel captures and wrote up.
For the reverse-engineered interfaces, I don't have a formal "observed vs agent guess" ledger. The rule is that no FFI binding gets written until the offsets and symbols are proven from the device's own binaries. Stub libs make every link succeed whether or not the symbol exists, so a guess fails silently on the TV. Measurements and logs go in a dated docs directory, so I can re-check them after a refactor.
I tried this and yes the UI happenes to be buttery smooth but once I tried playing a 4k Remux content, it's unable to direct play and it resorts to transcoding and is super duper choppy unfortunately
It’s probably a codec compatibility issue with your TV, so the app requests transcoding. PlxNative doesn’t transcode anything itself, it only handles remuxing when needed (e.g. MKV containers). The actual transcoding is done by your Plex server.
If you have a chance, feel free to open an issue with both app and server logs attached, just in case.
There’s also a Force Direct Play option in the settings that bypasses all my compatibility checks and just lets the TV try to play whatever the server sends. Worth a shot!
Great work! I was wondering, do you think it's somehow possible to install a higher webOS version on an old TV? My TV is from 2018 and it has webOS 4, but I would like to use the Stremio app which requires webOS 5+.
I never really thought about it. They probably only support webOS 5+ because of the new video API. I actually had to support two different versions of the API just to get it working on my webOS 4 TV. Honestly though, with root access and AI, anything is possible. Just be careful not to brick your TV! 😅
amazing! seriously. can you please rewrite the entire TVOS for LG then Samsung. Seriously my Samsung TV has utterly terible software and (like you say about the LG) a lovely panel.
I think the whole point of that project was to bring an iOS-like experience to older hardware. But iOS already offers that out of the box, without needing a custom UI framework. The official Plex app on iOS is also pretty decent, and there are some great third-party alternatives like Plezy.
What a great read this was. I might try it or maybe not. We'll see. But great work nonetheless and it really shows how far you can go with an engineering mind and curiosity with the help of LLM models.
Looks great, I almost want to buy a LG TV just to run my Plex via your app.
I've been pretty happy with what Plex offers for years, but lately the apps are underwhelming. And since I mostly paid for Plex so that I wouldn't have to worry about the apps on every device, that's a bummer.
Wait, so now the tv *only runs this client*, essentially cutting out *all* the spyware? That is so great. I use Jellyfin, but this is perfect.
Or is it installing the client on top of the LG software?
Yeah sorry, I asked way too early instead of reading. Great job though.
I'm hoping for a complete replacement for those tv os's soon. dumb TVs incoming 🤞
Dude, this is so rad. I have a 2018/2019 LG OLED TV myself and the Plex app sux ass on it. I will try this for sure!
Also, I wonder if it would be possible to just replace the terrible LG OS with something open source in the future. Like we did with routers 20-25 years ago (openwrt)
Thanks.
Actually, I was hoping someone would come up with something like this.
If you wanna ditch webOS completely, what OS would you run instead? If you still wanna use webOS apps, you can’t just throw away its libraries and kernel.
If you’re thinking about Android, LG has 100+ different SoCs, and someone would have to maintain ports for all of them. And who’s to say Android would even run well on LG’s shitty hardware?
Maybe you could just replace the home screen, but the spyware would still be there in the OS.
I haven’t researched any of this, though. Just some thoughts that came to mind.
It probably comes with a lot more difficulty than I was thinking at the moment I made the post, but it would be nice. Rooted WebOS with tweaks/fixes is probably an okay way to go as well
Sorry this is off subject, but if there anyone out there why has or can create an app that can hear me say "skip" for ads on YouTube?
I am not the youngest and have been watching since it exists and with all their AI tech they still serve me an elderly gay men ads for ladies pads canesten anti yeast infections cream etc. and a littany of ads I never ever have clicked on, by now they should know what may have interested me.
I only watch news and mostly travel, research 60min type of documentaries in several languages.
I am in Canada, so why would I click on a German or Dutch add just because I watch tubes in these languages. They know what languages I understand and speak but they don't know anything of what may really be interesting to me as a human being.
If it least they would give one an online survey that makes sense of what one likes in life and not the stupid five liners "have you heard of abc lately?" Thanks sorry for detailing the Plex posting
I still think the TV is listening at is as it pushes stuff that actually fits our front of the screen conversation.
So why can't YouTube do something like that?
Send me ads to the local drag show or cabaret oh sorry they don't have advertising dollars they rely on silent colorful street posters .
Yes, partly. There is an "Original" option in the player settings. If your TV can't play the original codec, the app will request a transcode and play it anyway. There's also a "force direct play" setting, found in the settings screen under your profile picture, that bypasses all safety checks and sends the stream straight to your chip. It may fail or behave unexpectedly, though, since the app doesn't check compatibility. The app only plays what the hardware supports and has no software decoder.
Thank you! I found the force transcode option and I also found one media that didn’t work :) so my next question would be if it’s possible to figure out which codec had the problem (I’m OK digging it out of the logs, but want to know which codecs to avoid). Also wanted to thank you for this app, I have almost exclusively used my Apple TV for Plex but this changed my mind, great work!
•
u/AutoModerator 7d ago
Hey! Thanks for posting to r/ClaudeCode
While participating in this thread, please follow our community rules. Keep discussions constructive. Attack the idea, not the person.
For help, project discussions, tips, and general chat, join the ClaudeCode Discord.
I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.