<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator>
  <link href="https://www.beyonderluu.com/feed.xml" rel="self" type="application/atom+xml" />
  <link href="https://www.beyonderluu.com/" rel="alternate" type="text/html" hreflang="en" />
  <updated>2026-06-04T06:08:22+00:00</updated>
  <id>https://www.beyonderluu.com/feed.xml</id>
  
  <title type="html">luthebao</title>
  <subtitle>Personal site of luthebao (BaoLT) — native apps, developer tools, and the occasional Flash emulator. Write-ups on the software I build.</subtitle>
  
  <author>
    <name>BaoLT</name>
    
  </author>
  
  
  
  
  <entry>
    <title type="html">Llflash — A Flash Player emulator in Rust, with a one-line RTMP host install</title>
    <link href="https://www.beyonderluu.com/2026/05/21/long-live-flash/" rel="alternate" type="text/html" title="Llflash — A Flash Player emulator in Rust, with a one-line RTMP host install" />
    <published>2026-05-21T00:00:00+00:00</published>
    <updated>2026-05-21T00:00:00+00:00</updated>
    <id>https://www.beyonderluu.com/2026/05/21/long-live-flash</id>
    <content type="html" xml:base="https://www.beyonderluu.com/2026/05/21/long-live-flash/">&lt;p&gt;&lt;strong&gt;Llflash&lt;/strong&gt; is an Adobe Flash Player emulator written in &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;, targeting both desktop and the web via WebAssembly. It’s a fork of &lt;a href=&quot;https://ruffle.rs/&quot;&gt;Ruffle&lt;/a&gt; with one headline addition: &lt;strong&gt;RTMP support&lt;/strong&gt;, delivered through a small native messaging host that pairs with the browser extension. The rest of the runtime tracks upstream — ActionScript 1, 2, and 3 are all supported, enough to bring most legacy &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.swf&lt;/code&gt; content back to life: games, animations, learning tools, and the multiplayer-streaming SWFs that vanilla Ruffle can’t reach because browsers don’t expose raw TCP.&lt;/p&gt;

&lt;p&gt;Desktop builds and the RTMP native messaging host are published on the &lt;a href=&quot;https://github.com/luthebao/luthebao/releases/tag/llflash&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llflash&lt;/code&gt; release&lt;/a&gt;. Questions, bug reports, and feature requests go through the &lt;a href=&quot;https://github.com/luthebao/luthebao/discussions&quot;&gt;luthebao discussions tab&lt;/a&gt; — there’s no public issue tracker.&lt;/p&gt;

&lt;h2 id=&quot;setup-in-three-steps&quot;&gt;Setup in three steps&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Install the browser extension.&lt;/strong&gt; &lt;em&gt;Coming soon&lt;/em&gt; — the Chrome Web Store / Firefox Add-ons listing isn’t published yet. Until then, you can side-load the unpacked extension from the &lt;a href=&quot;https://github.com/luthebao/luthebao/releases/tag/llflash&quot;&gt;release page&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Install the RTMP native messaging host&lt;/strong&gt; with the one-liner for your OS (see below). This is the small out-of-process helper that lets SWFs reach &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rtmp://&lt;/code&gt; servers.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Visit any page that uses Flash.&lt;/strong&gt; The extension picks up &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.swf&lt;/code&gt; embeds automatically and routes RTMP traffic through the host you just installed — no per-site configuration.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;install-the-rtmp-native-messaging-host&quot;&gt;Install the RTMP native messaging host&lt;/h2&gt;

&lt;p&gt;Llflash plays static SWFs entirely in the browser, but &lt;strong&gt;RTMP-based content&lt;/strong&gt; (legacy live-streaming SWFs, multiplayer games that talk to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rtmp://&lt;/code&gt; servers) needs an out-of-process helper — browsers can’t open raw TCP sockets. The &lt;strong&gt;RTMP native messaging host&lt;/strong&gt; is a small Rust binary the browser extension launches over Chrome / Firefox’s native-messaging protocol. Once registered, RTMP traffic inside any SWF is routed through it transparently.&lt;/p&gt;

&lt;p&gt;Pick the line that matches your OS.&lt;/p&gt;

&lt;h3 id=&quot;macos--linux&quot;&gt;macOS / Linux&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://github.com/luthebao/luthebao/releases/download/llflash/rtmp-host-install.sh | bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Supports &lt;strong&gt;macOS (Apple Silicon)&lt;/strong&gt; and &lt;strong&gt;Linux x86_64&lt;/strong&gt;. The script downloads the latest release tarball, drops the binary under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.llflash/rtmp-host/&lt;/code&gt;, and writes the native-messaging manifest (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;com.longliveflash.rtmp_host&lt;/code&gt;) into the right per-browser directory. Default target is Chrome — pass a browser name to install for a different one:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# chrome | chromium | edge | brave | firefox | all&lt;/span&gt;
curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://github.com/luthebao/luthebao/releases/download/llflash/rtmp-host-install.sh | bash &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;--&lt;/span&gt; firefox
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;windows&quot;&gt;Windows&lt;/h3&gt;

&lt;p&gt;In &lt;strong&gt;PowerShell&lt;/strong&gt;:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;irm&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://github.com/luthebao/luthebao/releases/download/llflash/rtmp-host-install.ps1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Same behaviour as the bash version: pulls the latest zip, extracts to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%LOCALAPPDATA%\LongLiveFlash\rtmp-host\&lt;/code&gt;, and registers the native-messaging manifest. To pass a browser argument, save the script first and run it locally:&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$u&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&apos;https://github.com/luthebao/luthebao/releases/download/llflash/rtmp-host-install.ps1&apos;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iwr&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$u&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-OutFile&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;rtmp-host-install.ps1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PowerShell&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-ExecutionPolicy&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Bypass&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;-File&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;\rtmp-host-install.ps1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After install, restart your browser and reload the extension — the host appears under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;chrome://extensions/&lt;/code&gt; (or the Firefox equivalent) and RTMP-backed SWFs should connect straight away.&lt;/p&gt;

&lt;h3 id=&quot;environment-overrides&quot;&gt;Environment overrides&lt;/h3&gt;

&lt;p&gt;Both scripts honour the same overrides if you need to pin a specific release or change the install location:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Variable&lt;/th&gt;
      &lt;th&gt;Default&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLFLASH_REPO&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;luthebao/luthebao&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLFLASH_TAG&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llflash&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;LLFLASH_INSTALL_DIR&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.llflash/rtmp-host&lt;/code&gt; (Unix) / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%LOCALAPPDATA%\LongLiveFlash\rtmp-host&lt;/code&gt; (Windows)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;desktop-builds&quot;&gt;Desktop builds&lt;/h2&gt;

&lt;p&gt;Standalone desktop builds are listed on the &lt;a href=&quot;https://github.com/luthebao/luthebao/releases/tag/llflash&quot;&gt;release page&lt;/a&gt; alongside the install scripts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llflash-rtmp-host-1.1.0-macOS-arm64.tar.gz&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llflash-rtmp-host-1.1.0-Linux-x64.tar.gz&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llflash-rtmp-host-1.1.0-Windows-x64.zip&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each archive contains the host binary plus the install script for that platform — useful if you’d rather audit the script and run it offline instead of piping from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;relationship-to-ruffle&quot;&gt;Relationship to Ruffle&lt;/h2&gt;

&lt;p&gt;Llflash is a fork of &lt;a href=&quot;https://github.com/ruffle-rs/ruffle&quot;&gt;Ruffle&lt;/a&gt;, not a rewrite. The AVM1/AVM2 interpreters, the renderer, and the SWF parser are Ruffle’s work — credit and thanks go to that project and its contributors. What this fork adds is the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rtmp://&lt;/code&gt; path: the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llflash-rtmp-host&lt;/code&gt; binary you just installed terminates the RTMP/RTMPE/RTMPT protocols outside the browser sandbox, and a thin bridge inside the wasm module forwards &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NetConnection&lt;/code&gt; / &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NetStream&lt;/code&gt; traffic to it. With that in place, SWFs that depend on Flash Media Server, Wowza, or any RTMP origin keep working — which is the gap that kept a noticeable slice of legacy Flash content from running under stock Ruffle.&lt;/p&gt;

&lt;p&gt;Everything else — including most ActionScript edge cases, codec coverage, and the desktop player — behaves like upstream Ruffle. Questions, bug reports, and feature requests live on the &lt;a href=&quot;https://github.com/luthebao/luthebao/discussions&quot;&gt;luthebao discussions tab&lt;/a&gt; (the source repo is private, so there’s no public issue tracker)&lt;/p&gt;

&lt;h2 id=&quot;privacy&quot;&gt;Privacy&lt;/h2&gt;

&lt;p&gt;Long Live Flash respects user privacy. The browser extension searches website HTML for embedded Flash content without storing or transmitting browsing activity.&lt;/p&gt;

&lt;p&gt;Flash content may store data locally using browser LocalStorage APIs and make network requests to third-party servers, potentially transmitting personally identifiable or “fingerprintable” information. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;llflash-rtmp-host&lt;/code&gt; extends that surface in one direction only: when a SWF opens an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rtmp://&lt;/code&gt; connection, the host establishes a TCP connection to that origin on the SWF’s behalf. Llflash itself does not inspect, log, or retain RTMP payloads — they pass through the host and back to the wasm runtime — but the destination server will see traffic from your IP address, exactly as it would have under the original Flash Player.&lt;/p&gt;

&lt;p&gt;LLFlash stores settings locally via the browser’s extension storage API. These settings don’t contain identifying information and aren’t transmitted to servers.&lt;/p&gt;

&lt;p&gt;When errors occur, users can optionally submit crash reports through the &lt;a href=&quot;https://github.com/luthebao/luthebao/discussions&quot;&gt;luthebao discussions tab&lt;/a&gt;. These reports include browser and site information but aren’t stored or transmitted without explicit user consent.&lt;/p&gt;

&lt;p&gt;The project is a fork of &lt;a href=&quot;https://github.com/ruffle-rs/ruffle&quot;&gt;Ruffle&lt;/a&gt;, which is open-source; LLflash’s additions are distributed via the &lt;a href=&quot;https://github.com/luthebao/luthebao/releases/tag/llflash&quot;&gt;release page&lt;/a&gt; above.&lt;/p&gt;

&lt;p&gt;Users should exercise caution with untrusted content. LLflash isn’t responsible for third-party privacy practices, and we encourage reviewing the applicable privacy policies and terms of the websites and services visited.&lt;/p&gt;</content>
    
    
    <author>
      <name>BaoLT</name>
    </author>
    
    <summary type="html">A Rust Flash Player emulator — a Ruffle fork that adds RTMP support through a one-line native-messaging host, bringing legacy streaming and multiplayer SWFs back to life.</summary>
    <category term="rust" /><category term="flash" /><category term="wasm" />
  </entry>
  
  <entry>
    <title type="html">MMStock — Native terminal for the Vietnamese stock-futures market</title>
    <link href="https://www.beyonderluu.com/2026/05/20/mm-vnstock/" rel="alternate" type="text/html" title="MMStock — Native terminal for the Vietnamese stock-futures market" />
    <published>2026-05-20T00:00:00+00:00</published>
    <updated>2026-05-20T00:00:00+00:00</updated>
    <id>https://www.beyonderluu.com/2026/05/20/mm-vnstock</id>
    <content type="html" xml:base="https://www.beyonderluu.com/2026/05/20/mm-vnstock/">&lt;p&gt;&lt;strong&gt;MMStock&lt;/strong&gt; is a native desktop terminal for the Vietnamese stock-futures market. It connects directly to the VPS data feed (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;web7.vps.com.vn&lt;/code&gt;) — no separate backend service in between — and renders charts, indicators, and a real-time price stream entirely on the client.&lt;/p&gt;

&lt;p&gt;The app is written in &lt;a href=&quot;https://odin-lang.org/&quot;&gt;Odin&lt;/a&gt; on top of &lt;a href=&quot;https://github.com/floooh/sokol&quot;&gt;Sokol&lt;/a&gt;, &lt;a href=&quot;https://github.com/ocornut/imgui&quot;&gt;Dear ImGui&lt;/a&gt;, and &lt;a href=&quot;https://github.com/epezent/implot&quot;&gt;ImPlot&lt;/a&gt;. Builds run on macOS (Apple Silicon and Intel), Linux x86_64, and Windows x86_64.&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/assets/img/posts/mmstock/terminal.png&quot; alt=&quot;MMStock terminal showing two side-by-side chart panels with candlesticks, VPVR volume-by-price overlays, BLT-MACD and BLT-RSI indicator subpanels, and a multi-timeframe table&quot; /&gt;
  &lt;figcaption&gt;MMStock — two chart panels with VPVR overlays and the BLT-MACD/RSI indicators&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h2 id=&quot;download&quot;&gt;Download&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/luthebao/luthebao/releases/tag/mmstock&quot;&gt;&lt;strong&gt;Download MMStock&lt;/strong&gt;&lt;/a&gt; — macOS and Windows builds available on the release page.&lt;/p&gt;

&lt;h3 id=&quot;one-liner-install&quot;&gt;One-liner install&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;macOS / Linux:&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-sh highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://github.com/luthebao/luthebao/releases/download/mmstock/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Windows (PowerShell):&lt;/strong&gt;&lt;/p&gt;

&lt;div class=&quot;language-powershell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;irm&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;https://github.com/luthebao/luthebao/releases/download/mmstock/install.ps1&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iex&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-it-does&quot;&gt;What it does&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Charts&lt;/strong&gt; — candlestick, line, and Heiken Ashi, across multiple timeframes (1m, 5m, 15m, 30m, 1H, 4H, 8H, 1D, 1W, 1M).&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Real-time stream&lt;/strong&gt; — live prices over WSS, historical bars over HTTPS, both from VPS directly.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Drawing tools&lt;/strong&gt; — per-chart horizontal line, rectangle, and point-line annotations.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Indicators&lt;/strong&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;strong&gt;VPVR&lt;/strong&gt; — volume-by-price overlay.&lt;/li&gt;
      &lt;li&gt;&lt;strong&gt;BLT-ID-RSI&lt;/strong&gt; — a Pine-script port combining RSI with Fast (RMA 5) and Slow (WMA 45) moving averages, regular and hidden bull/bear divergence detection, a VMC gold buy signal, a Stoch-RSI sell signal, and a configurable multi-timeframe table.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;architecture-in-one-paragraph&quot;&gt;Architecture in one paragraph&lt;/h2&gt;

&lt;p&gt;A single Odin binary holds the UI (ImGui/ImPlot rendered through Sokol), the VPS HTTPS + WSS client, and a local SQLite store for cached bars. There is no server-side component to deploy — the terminal is the entire app, and updates ship as new binaries.&lt;/p&gt;

&lt;h2 id=&quot;why-a-native-client&quot;&gt;Why a native client&lt;/h2&gt;

&lt;p&gt;Two reasons. First, charting tens of thousands of bars at 60 fps with smooth pan/zoom is straightforward in ImPlot and painful in a browser. Second, going straight to the exchange feed cuts an entire layer of infrastructure: no API gateway, no backend cache, no queue — fewer moving parts to break and nothing to host.&lt;/p&gt;

&lt;h2 id=&quot;status&quot;&gt;Status&lt;/h2&gt;

&lt;p&gt;Active development. The Vietnamese stock-futures market is a relatively niche audience, so MMStock is built primarily as a tool I want to use myself, with an eye on making it pleasant for anyone with a similar workflow.&lt;/p&gt;</content>
    
    
    <author>
      <name>BaoLT</name>
    </author>
    
    <summary type="html">A native desktop terminal for the Vietnamese stock-futures market, written in Odin — charts, indicators, and a real-time VPS feed with no backend in between.</summary>
    <category term="odin" /><category term="trading" /><category term="desktop" />
  </entry>
  
  <entry>
    <title type="html">mac-cli — A multi-purpose macOS command-line tool</title>
    <link href="https://www.beyonderluu.com/2026/05/20/mac-cli/" rel="alternate" type="text/html" title="mac-cli — A multi-purpose macOS command-line tool" />
    <published>2026-05-20T00:00:00+00:00</published>
    <updated>2026-05-20T00:00:00+00:00</updated>
    <id>https://www.beyonderluu.com/2026/05/20/mac-cli</id>
    <content type="html" xml:base="https://www.beyonderluu.com/2026/05/20/mac-cli/">&lt;p&gt;&lt;strong&gt;mac-cli&lt;/strong&gt; is a multi-purpose command-line tool for macOS, written in &lt;a href=&quot;https://odin-lang.org/&quot;&gt;Odin&lt;/a&gt;. It bundles several utilities I reach for daily — disk cleaning, image/video optimisation, and screenshots — behind one small, agent-friendly binary. Currently ships an Apple Silicon (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arm64&lt;/code&gt;) build only.&lt;/p&gt;

&lt;p&gt;Source and releases live at &lt;a href=&quot;https://github.com/luthebao/mac-cli&quot;&gt;github.com/luthebao/mac-cli&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;install&quot;&gt;Install&lt;/h2&gt;

&lt;p&gt;One-liner — pulls the latest release binary, no Odin toolchain required:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;curl &lt;span class=&quot;nt&quot;&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/luthebao/mac-cli/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The script downloads the latest tarball, picks a sensible install dir (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/bin&lt;/code&gt; if writable, otherwise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.local/bin&lt;/code&gt;), strips the macOS quarantine xattr so Gatekeeper doesn’t block the first run, and prints a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PATH&lt;/code&gt; hint if the chosen dir isn’t already on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PATH&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;self-update&quot;&gt;Self-update&lt;/h2&gt;

&lt;p&gt;The binary updates itself — same install logic, no flags needed:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mac-cli update            &lt;span class=&quot;c&quot;&gt;# install latest if newer&lt;/span&gt;
mac-cli update &lt;span class=&quot;nt&quot;&gt;--check&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;# report only; exits non-zero when update available&lt;/span&gt;
mac-cli update &lt;span class=&quot;nt&quot;&gt;--force&lt;/span&gt;    &lt;span class=&quot;c&quot;&gt;# re-run the installer even if already current&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;commands&quot;&gt;Commands&lt;/h2&gt;

&lt;h3 id=&quot;clean--disk-cleaner&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clean&lt;/code&gt; — disk cleaner&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mac-cli clean                        &lt;span class=&quot;c&quot;&gt;# interactive cleaner&lt;/span&gt;
mac-cli clean &lt;span class=&quot;nt&quot;&gt;--risky&lt;/span&gt;                &lt;span class=&quot;c&quot;&gt;# include risky categories&lt;/span&gt;
mac-cli clean categories             &lt;span class=&quot;c&quot;&gt;# list all 16 cleanable categories&lt;/span&gt;
mac-cli clean uninstall              &lt;span class=&quot;c&quot;&gt;# remove apps + their leftovers&lt;/span&gt;
mac-cli clean maintenance &lt;span class=&quot;nt&quot;&gt;--dns&lt;/span&gt;      &lt;span class=&quot;c&quot;&gt;# flush DNS cache&lt;/span&gt;
mac-cli clean backup &lt;span class=&quot;nt&quot;&gt;--list&lt;/span&gt;          &lt;span class=&quot;c&quot;&gt;# list pre-delete backups&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The interactive cleaner scans every category, then shows exactly what it will remove and how much space you get back before you commit:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/assets/img/posts/mac-cli/clean-scan.png&quot; alt=&quot;mac-cli clean scanning the Mac and reporting 17.5 GB cleanable, with a summary of 205 items and a [Y/n] confirmation prompt&quot; /&gt;
  &lt;figcaption&gt;mac-cli clean — scan summary and confirmation prompt&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Anything outside a known-safe path is refused rather than deleted, so a stray bad rule can’t touch the wrong directory. When it finishes you get a tally of what was freed:&lt;/p&gt;

&lt;figure&gt;
  &lt;img src=&quot;/assets/img/posts/mac-cli/clean-result.png&quot; alt=&quot;mac-cli clean output showing several &apos;refused (path not safe)&apos; lines, then &apos;Freed 7.5 GB of disk space! Cleaned 159 items&apos;&quot; /&gt;
  &lt;figcaption&gt;mac-cli clean — “path not safe” refusals and the final freed-space tally&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id=&quot;clop--image--video-optimiser&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;clop&lt;/code&gt; — image &amp;amp; video optimiser&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mac-cli clop                         &lt;span class=&quot;c&quot;&gt;# interactive picker&lt;/span&gt;
mac-cli clop &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; photo.png            &lt;span class=&quot;c&quot;&gt;# optimise in place&lt;/span&gt;
mac-cli clop &lt;span class=&quot;nt&quot;&gt;-o&lt;/span&gt; ~/Pictures &lt;span class=&quot;nt&quot;&gt;-r&lt;/span&gt;        &lt;span class=&quot;c&quot;&gt;# recurse into a directory&lt;/span&gt;
mac-cli clop &lt;span class=&quot;nt&quot;&gt;-d&lt;/span&gt; 50% clip.mp4         &lt;span class=&quot;c&quot;&gt;# downscale by factor&lt;/span&gt;
mac-cli clop &lt;span class=&quot;nt&quot;&gt;-c&lt;/span&gt; webp cover.png       &lt;span class=&quot;c&quot;&gt;# convert image format&lt;/span&gt;
mac-cli clop &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt; IMG_2156.jpg         &lt;span class=&quot;c&quot;&gt;# strip EXIF metadata&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Shells out to format-specific CLIs (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pngquant&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jpegoptim&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gifsicle&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ffmpeg&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vips&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cwebp&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;heif-enc&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exiftool&lt;/code&gt;). Missing tools trigger an interactive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;brew install&lt;/code&gt; prompt on first use. Supported formats: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.png .jpg .jpeg .gif&lt;/code&gt; (images) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.mp4 .mov .m4v&lt;/code&gt; (videos).&lt;/p&gt;

&lt;h3 id=&quot;shot--screenshots&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;shot&lt;/code&gt; — screenshots&lt;/h3&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;mac-cli shot                         &lt;span class=&quot;c&quot;&gt;# interactive picker (type to filter)&lt;/span&gt;
mac-cli shot &lt;span class=&quot;nt&quot;&gt;-s&lt;/span&gt;                      &lt;span class=&quot;c&quot;&gt;# capture full screen&lt;/span&gt;
mac-cli shot &lt;span class=&quot;nt&quot;&gt;-l&lt;/span&gt;                      &lt;span class=&quot;c&quot;&gt;# list running GUI apps with PIDs&lt;/span&gt;
mac-cli shot &lt;span class=&quot;nt&quot;&gt;-p&lt;/span&gt; 1234                 &lt;span class=&quot;c&quot;&gt;# capture a specific app by PID&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;All screenshots land in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/Desktop&lt;/code&gt; as PNGs. First run may prompt for the Screen Recording permission in System Settings → Privacy.&lt;/p&gt;

&lt;h2 id=&quot;claude-code-agent-skill&quot;&gt;Claude Code agent skill&lt;/h2&gt;

&lt;p&gt;If you use &lt;a href=&quot;https://claude.com/claude-code&quot;&gt;Claude Code&lt;/a&gt;, install the companion agent skill so Claude can drive &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac-cli&lt;/code&gt; for you — cleaning caches, taking app-specific screenshots, optimising media, and so on:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;npx skills add luthebao/mac-cli
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The skill assumes the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mac-cli&lt;/code&gt; binary is already on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$PATH&lt;/code&gt;, so install that first.&lt;/p&gt;

&lt;h2 id=&quot;build-from-source&quot;&gt;Build from source&lt;/h2&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;git clone https://github.com/luthebao/mac-cli.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;mac-cli
make build                           &lt;span class=&quot;c&quot;&gt;# → build/mac-cli&lt;/span&gt;
make &lt;span class=&quot;nb&quot;&gt;test
&lt;/span&gt;make &lt;span class=&quot;nb&quot;&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Licensed under MIT.&lt;/p&gt;</content>
    
    
    <author>
      <name>BaoLT</name>
    </author>
    
    <summary type="html">A multi-purpose macOS command-line tool in Odin — disk cleaning, image and video optimisation, and screenshots behind one small, agent-friendly binary.</summary>
    <category term="odin" /><category term="macos" /><category term="cli" />
  </entry>
  
</feed>
