<?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: Junyi Zhang</title>
    <description>The latest articles on DEV Community by Junyi Zhang (@junyiz).</description>
    <link>https://dev.to/junyiz</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%2F3902030%2Fd0f55722-f8c2-483a-b4b1-2bc0fbc77886.png</url>
      <title>DEV Community: Junyi Zhang</title>
      <link>https://dev.to/junyiz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/junyiz"/>
    <language>en</language>
    <item>
      <title>How to Return 410 Gone on Cloudflare Pages (The \_redirects Gotcha</title>
      <dc:creator>Junyi Zhang</dc:creator>
      <pubDate>Mon, 27 Jul 2026 23:45:22 +0000</pubDate>
      <link>https://dev.to/junyiz/how-to-return-410-gone-on-cloudflare-pages-the-redirects-gotcha-48je</link>
      <guid>https://dev.to/junyiz/how-to-return-410-gone-on-cloudflare-pages-the-redirects-gotcha-48je</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;I registered a domain for a new project. Shortly after launch, Google Search Console started flooding with mysterious 404 errors — URLs like &lt;code&gt;/post/xxx&lt;/code&gt; and &lt;code&gt;/category-xxx&lt;/code&gt;, the classic WordPress path patterns. Turns out the domain had a previous owner who ran a WordPress site, and Google still had those old pages indexed.&lt;/p&gt;

&lt;p&gt;When search engines see 404s on old URLs, they keep retrying. Better to tell them unequivocally: "This content is gone for good" — that's what 410 Gone is for.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pitfall: _redirects Only Supports 3xx
&lt;/h2&gt;

&lt;p&gt;My first instinct was to add rules to &lt;code&gt;_redirects&lt;/code&gt;:&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="n"&gt;post&lt;/span&gt;/*    &lt;span class="m"&gt;410&lt;/span&gt;
/&lt;span class="n"&gt;category&lt;/span&gt;-*    &lt;span class="m"&gt;410&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deployed it. Nothing happened — those URLs still returned 404.&lt;/p&gt;

&lt;p&gt;After digging into the &lt;a href="https://developers.cloudflare.com/pages/configuration/redirects/" rel="noopener noreferrer"&gt;Cloudflare Pages docs&lt;/a&gt;, the answer emerged: &lt;strong&gt;&lt;code&gt;_redirects&lt;/code&gt; only supports five status codes — 301, 302, 303, 307, and 308&lt;/strong&gt;. Writing &lt;code&gt;410&lt;/code&gt; gets silently ignored. No warning, no error, nothing.&lt;/p&gt;

&lt;p&gt;As a bonus facepalm: my test &lt;code&gt;301&lt;/code&gt; redirect wasn't working either, because I had the format backwards:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/test-redirect  301  /     ← Wrong: destination and status code are swapped
/test-redirect  /  301     ← Correct: source → destination → status code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Fix: Cloudflare Pages Functions
&lt;/h2&gt;

&lt;p&gt;Use a Cloudflare Pages Function as middleware. Create &lt;code&gt;functions/[[path]].js&lt;/code&gt; at the project root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Intercept old WordPress URLs, return 410 Gone&lt;/span&gt;
&lt;span class="c1"&gt;// Pass everything else through to static assets&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GONE_PATTERNS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;post&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;category-/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;author-/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;page_/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\/&lt;/span&gt;&lt;span class="sr"&gt;date-/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GONE_EXACT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/.IGV0hOcNusVJOgqoD1HuWTk0PssdueKB&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;pathname&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GONE_PATTERNS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;GONE_EXACT&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;410 Gone — This content has been permanently removed.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;410&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text/plain; charset=utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Matches old WordPress URL patterns → returns 410&lt;/li&gt;
&lt;li&gt;Everything else → &lt;code&gt;context.next()&lt;/code&gt; passes through to static assets with zero overhead&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Place the &lt;code&gt;functions/&lt;/code&gt; directory at the project root (not inside &lt;code&gt;src/&lt;/code&gt; or &lt;code&gt;public/&lt;/code&gt;). Cloudflare Pages auto-detects it and enables the Functions runtime — no extra configuration needed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✨ Uploading _redirects
✨ Uploading Functions bundle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verification
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"HTTP %{http_code}"&lt;/span&gt; https://example.com/post/hello-world
HTTP 410

&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"HTTP %{http_code}"&lt;/span&gt; https://example.com/category-tech
HTTP 410

&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /dev/null &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="s2"&gt;"HTTP %{http_code}"&lt;/span&gt; https://example.com/
HTTP 200
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3xx redirects&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;_redirects&lt;/code&gt; file&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4xx / 5xx status codes&lt;/td&gt;
&lt;td&gt;Cloudflare Pages Functions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex routing (rate limiting, auth, etc.)&lt;/td&gt;
&lt;td&gt;Functions or Workers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;em&gt;This was a real-world pitfall encountered while building &lt;a href="https://bgmbox.com" rel="noopener noreferrer"&gt;BGM Box&lt;/a&gt;, a free online BRSTM converter and player for Nintendo game audio. Convert 100+ formats (MP3, WAV, OGG, FLAC, ADX, HCA, FSB, WEM...) to BRSTM, BCSTM, and BFSTM — all in your browser with no sign-up and no file uploads. Give it a try!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>cloudflare</category>
    </item>
    <item>
      <title>How I Built a BRSTM Converter with WebAssembly — Technical Deep Dive</title>
      <dc:creator>Junyi Zhang</dc:creator>
      <pubDate>Fri, 24 Jul 2026 07:50:10 +0000</pubDate>
      <link>https://dev.to/junyiz/how-i-built-a-brstm-converter-with-webassembly-technical-deep-dive-17jf</link>
      <guid>https://dev.to/junyiz/how-i-built-a-brstm-converter-with-webassembly-technical-deep-dive-17jf</guid>
      <description>&lt;h2&gt;
  
  
  The Problem: No Browser-Based BRSTM Tool Existed
&lt;/h2&gt;

&lt;p&gt;Every existing BRSTM converter was a desktop app — BrawlBox for Windows, Looping Audio Converter (a .NET Framework app written in C#), or command-line tools that needed compiling from source. If you were on a Mac, on Linux, or wanted to quickly convert a file without installing anything, you were out of luck.&lt;/p&gt;

&lt;p&gt;The core challenge: BRSTM encoding requires C libraries (DspTool) that were never designed to run in a browser. And decoding game audio formats like ADX, HCA, and FSB requires vgmstream, a massive C codebase with decades of reverse-engineered format support.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture: Three WebAssembly Modules in One Browser Tab
&lt;/h2&gt;

&lt;p&gt;The workflow splits processing away from the main UI thread into background Web Workers, maintaining a butter-smooth 60 FPS user interface during complex encoding tasks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+-------------------------------------------------------------------+
|                        MAIN THREAD (UI)                           |
|  - Drag &amp;amp; Drop Handling      - Audio Preview (Web Audio API)      |
|  - Progress Bar Rendering    - SEO &amp;amp; Route State                  |
+-------------------------------------------------------------------+
                                 |
                          postMessage()
                                 v
+-------------------------------------------------------------------+
|                     WEB WORKERS (Background)                      |
|                                                                   |
|  1. VgmstreamWorker      2. EncoderWorker     3. Export Worker    |
|   [vgmstream.wasm]        [sound.wasm]        [lame / vorbis]     |
|   Decode to PCM          Encode to BRSTM       Export MP3/OGG     |
+-------------------------------------------------------------------+

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1. &lt;code&gt;vgmstream.wasm&lt;/code&gt; — The Universal Decoder (4.1 MB)
&lt;/h3&gt;

&lt;p&gt;vgmstream is the industry-standard game audio decoding library. It supports 100+ formats — from Nintendo's BRSTM/BCSTM/BFSTM to CRI's ADX/HCA, Microsoft's XMA, FMOD's FSB, and Sony's ATRAC3. The vgmstream project provides a pre-built WASM binary, which I wrapped in a Web Worker so decoding never blocks the UI thread.&lt;/p&gt;

&lt;p&gt;The hardest part was integrating with the Emscripten virtual filesystem that vgmstream's WASM build uses internally. Files are written to the virtual FS via FS.writeFile(), decoded via vgmstream's CLI interface (callMain(['-o', '/out.wav', '/in.bcstm'])), then read back from FS.readFile() — all inside a Web Worker.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;code&gt;sound.wasm&lt;/code&gt; — The BRSTM Encoder (176 KB)
&lt;/h3&gt;

&lt;p&gt;The encoding process relies on &lt;strong&gt;DspTool&lt;/strong&gt; (developed by Alex Barney), an MIT-licensed C library designed for generating &lt;code&gt;BRSTM&lt;/code&gt;, &lt;code&gt;BCSTM&lt;/code&gt;, and &lt;code&gt;BFSTM&lt;/code&gt; files.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes raw PCM audio data and outputs a fully compliant Nintendo audio file complete with loop point metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory Management:&lt;/strong&gt; PCM data is pushed into the WASM heap using Emscripten’s &lt;code&gt;_malloc&lt;/code&gt; and converted to match Nintendo DSP ADPCM standards.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;code&gt;lame.min.js&lt;/code&gt; + &lt;code&gt;vorbis-encoder-bundle&lt;/code&gt; — The Export Encoders
&lt;/h3&gt;

&lt;p&gt;For reverse conversions (&lt;code&gt;BRSTM → MP3&lt;/code&gt;, &lt;code&gt;BCSTM → OGG&lt;/code&gt;, &lt;code&gt;FSB → MP3&lt;/code&gt;), browser-native encoders are required:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;MP3:&lt;/strong&gt; Handled efficiently via &lt;code&gt;lamejs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OGG Vorbis:&lt;/strong&gt; &lt;code&gt;libvorbis.js&lt;/code&gt; compiled with Emscripten, bundled with Browserify to ensure compatibility with &lt;code&gt;importScripts()&lt;/code&gt; inside Web Workers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Technical Deep-Dive: The Interleaved vs. Planar PCM Bug
&lt;/h2&gt;

&lt;p&gt;During development, multi-channel audio output resulted in harsh, garbled noise. Tracking this down required comparing hex dumps of PCM buffers against expected byte layouts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Interleaved PCM (vgmstream output / Web Audio API):
[ L0, R0, L1, R1, L2, R2, ... ]

Planar PCM (DspTool expectation):
[ L0, L1, L2, ... ] [ R0, R1, R2, ... ]

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bug stemmed from an indexing calculation error during the deinterleaving pass:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Incorrect Deinterleaving Formula&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pcm&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;channelIndex&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;sampleLength&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Correct Deinterleaving Formula&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pcm&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;totalChannels&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;channelIndex&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By ensuring proper data transformation before allocation to the WASM heap, multi-channel audio was rendered cleanly without UI thread stutter.&lt;/p&gt;




&lt;h2&gt;
  
  
  Web Worker Memory Optimization
&lt;/h2&gt;

&lt;p&gt;Loading a 4.1 MB WASM module multiple times can quickly lead to heavy memory consumption. To keep performance optimal:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Persistent Worker Allocation:&lt;/strong&gt; Web Workers are instantiated once and kept alive throughout the session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transferable Objects:&lt;/strong&gt; Large &lt;code&gt;ArrayBuffer&lt;/code&gt; payloads exchanged via &lt;code&gt;postMessage()&lt;/code&gt; use transferables (&lt;code&gt;postMessage(data, [data.buffer])&lt;/code&gt;), transferring ownership zero-copy rather than cloning large audio arrays.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WASM Module Caching:&lt;/strong&gt; Compiled WebAssembly modules are cached in IndexedDB to bypass recompilation overhead on subsequent page visits.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Try It Out
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;BGM Box&lt;/strong&gt; is 100% free and open about its technical implementation. Every conversion process executes entirely inside your client browser — no server-side uploading or processing required.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;&lt;a href="https://bgmbox.com" rel="noopener noreferrer"&gt;bgmbox.com&lt;/a&gt;&lt;/strong&gt; — &lt;em&gt;Convert, Play, Loop. All in one box.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>brstm</category>
      <category>vgmstream</category>
      <category>dsptool</category>
    </item>
    <item>
      <title>Full Analysis of AI Agent Security Tools: Onecli, Sigcli, Agent Vault, Ren AI Proxy, and FakeKey</title>
      <dc:creator>Junyi Zhang</dc:creator>
      <pubDate>Tue, 28 Apr 2026 09:29:39 +0000</pubDate>
      <link>https://dev.to/junyiz/full-analysis-of-ai-agent-security-tools-onecli-sigcli-agent-vault-ren-ai-proxy-and-fakekey-3l6f</link>
      <guid>https://dev.to/junyiz/full-analysis-of-ai-agent-security-tools-onecli-sigcli-agent-vault-ren-ai-proxy-and-fakekey-3l6f</guid>
      <description>&lt;h1&gt;
  
  
  Full Analysis of AI Agent Security Tools: Onecli, Sigcli, Agent Vault, Ren AI Proxy, and FakeKey
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Background: An Emerging Security Need
&lt;/h2&gt;

&lt;p&gt;The rise of AI agents and coding assistants (such as Claude Code, Cursor) is bringing brand‑new security challenges to developers. Your project directory may quietly contain a &lt;code&gt;.env&lt;/code&gt; file storing various API keys for OpenAI, Anthropic, Alibaba Cloud, Feishu – many of which are linked to credit cards.&lt;/p&gt;

&lt;p&gt;The recent LiteLLM Axios supply‑chain attack has made the issue acute: when your development environment can be scanned by malicious dependencies at any time, storing API keys in plaintext is like walking around naked.&lt;/p&gt;

&lt;p&gt;Hence, a new category of tools has emerged – &lt;strong&gt;credential security tools for AI agents&lt;/strong&gt;. These tools share a highly consistent goal: enabling AI agents to securely access external services without needing (and being unable) to see the real API keys.&lt;/p&gt;

&lt;p&gt;Below is a comprehensive overview of five representative products.&lt;/p&gt;




&lt;h2&gt;
  
  
  Product Definitions at a Glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;Core Definition&lt;/th&gt;
&lt;th&gt;One‑Sentence Positioning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Onecli&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open‑source credential vault that gives AI agents secure access to services&lt;/td&gt;
&lt;td&gt;No key exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sigcli&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Authentication CLI &amp;amp; proxy for AI agents&lt;/td&gt;
&lt;td&gt;Grant access, not credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Agent Vault&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HTTP credential proxy and vault&lt;/td&gt;
&lt;td&gt;Dual role: proxy + vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ren AI Proxy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;LLM API sharing proxy&lt;/td&gt;
&lt;td&gt;Share quota securely without exposing keys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FakeKey&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Rust‑based API key security proxy&lt;/td&gt;
&lt;td&gt;Replace real keys with fake ones – make leaks meaningless&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Detailed Product Descriptions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Onecli
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://www.onecli.sh/" rel="noopener noreferrer"&gt;https://www.onecli.sh/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Positioning&lt;/strong&gt;: Open‑source credential vault&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Onecli is a general‑purpose credential management tool, specifically optimised for AI agent scenarios. It acts as a secure “middleman” – the AI agent requests credentials from Onecli, and Onecli handles the interaction with the real service. Throughout the process, the original API key remains completely invisible to the agent.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Sigcli
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://sigcli.ai/" rel="noopener noreferrer"&gt;https://sigcli.ai/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Positioning&lt;/strong&gt;: Authentication CLI &amp;amp; proxy for AI agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The name Sigcli hints at its core capability – authentication. It is more than a credential proxy; it is a complete identity verification solution. Its design philosophy is “grant the agent access, not your credentials” – meaning you can finely control what the agent can and cannot do without handing over your keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Agent Vault
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Documentation&lt;/strong&gt;: &lt;a href="https://docs.agent-vault.dev/" rel="noopener noreferrer"&gt;https://docs.agent-vault.dev/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Positioning&lt;/strong&gt;: HTTP credential proxy and vault&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agent Vault’s product name directly reflects its functionality: it is a proxy plus a vault. The AI agent sends HTTP requests to it, and Agent Vault dynamically replaces fake credentials with real keys before the request reaches the target API.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Ren AI Proxy
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Website&lt;/strong&gt;: &lt;a href="https://ren.im" rel="noopener noreferrer"&gt;https://ren.im&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Positioning&lt;/strong&gt;: LLM API sharing proxy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ren AI Proxy has the most unique positioning in this category. Its goal is not “protect my own keys from leakage” but rather &lt;strong&gt;“share my API quota with others without exposing my keys”&lt;/strong&gt;. For example, if you have unused quota from a Coding Plan, you can share it with your team or friends via Ren AI Proxy. It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LAN sharing&lt;/li&gt;
&lt;li&gt;Internet sharing (using intranet penetration tools such as Tunelo)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. FakeKey
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/happyvibing/fakekey" rel="noopener noreferrer"&gt;https://github.com/happyvibing/fakekey&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Positioning&lt;/strong&gt;: Rust‑based API key security proxy – replace real keys with fake ones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FakeKey has the most radical and direct idea: &lt;strong&gt;“make leaks meaningless”&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  How it works
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Client Agent (uses fake key sk-xxx_fk) 
    → FakeKey Proxy (TLS decryption, identify replacement rules) 
        → External API (uses real key sk-xxx)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The AI agent and all dependencies only ever see fake keys (e.g., &lt;code&gt;sk-xxx_fk&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Real keys are encrypted and stored in the system’s built‑in key manager (e.g., macOS Keychain).&lt;/li&gt;
&lt;li&gt;Only when an HTTP/HTTPS request is made does the FakeKey proxy replace the fake key with the real one in real time.&lt;/li&gt;
&lt;li&gt;If any dependency is compromised, the attacker can at most steal meaningless fake strings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Quick Start
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# One‑line installation&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/happyvibing/fakekey/main/install.sh | bash

&lt;span class="c"&gt;# Initialisation and onboarding&lt;/span&gt;
fakekey onboard

&lt;span class="c"&gt;# Run your favourite tool (leak‑free)&lt;/span&gt;
fakekey run claude
fakekey run pi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FakeKey is written entirely in Rust, requires no Docker, and emphasises being lightweight, fast, and deeply integrated with the system’s native key management.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technical Route Comparison
&lt;/h2&gt;

&lt;p&gt;The products above can be divided into two technical schools:&lt;/p&gt;

&lt;h3&gt;
  
  
  School 1: Proxy + Dynamic Replacement (Onecli, Sigcli, Agent Vault, FakeKey)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core idea&lt;/strong&gt;: Place a local proxy between the AI agent and the target API. The agent uses fake credentials; the proxy swaps them for real ones just before sending the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problems solved&lt;/strong&gt;: Credential leakage from dependency poisoning, log leaks, environment variable scanning, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Differences among representatives&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FakeKey&lt;/strong&gt;: Most radical – “fake‑key replacement” is in its name and core.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agent Vault&lt;/strong&gt;: Emphasises being an HTTP credential proxy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onecli / Sigcli&lt;/strong&gt;: Naming highlights “credential vault” and “authentication” concepts.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  School 2: Permission Sharing (Ren AI Proxy)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core idea&lt;/strong&gt;: Still a proxy model, but the goal shifts from “protecting yourself” to “securely sharing quota”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problems solved&lt;/strong&gt;: How to authorise access without handing over keys in multi‑user / multi‑machine environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unique value&lt;/strong&gt;: It addresses “trust transfer” rather than just “leak prevention”.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Selection Recommendations
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;If your need is…&lt;/th&gt;
&lt;th&gt;Recommended products&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Protect your local AI coding environment&lt;/td&gt;
&lt;td&gt;Onecli, Sigcli, Agent Vault, FakeKey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deep integration with system keychain (macOS Keychain)&lt;/td&gt;
&lt;td&gt;FakeKey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preference for lightweight CLI, Rust implementation&lt;/td&gt;
&lt;td&gt;FakeKey&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Preference for a generic HTTP proxy approach&lt;/td&gt;
&lt;td&gt;Agent Vault&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Share API quota with others (without exposing keys)&lt;/td&gt;
&lt;td&gt;Ren AI Proxy&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Conclusion: A New Security Category Taking Shape
&lt;/h2&gt;

&lt;p&gt;These five products together reflect a trend: as AI agents become part of developers’ daily toolchains, &lt;strong&gt;credential security in agent environments&lt;/strong&gt; is emerging as an independent and important sub‑domain of security.&lt;/p&gt;

&lt;p&gt;Their core insight is: in a runtime environment where absolute trust is impossible, instead of trying to “prevent poisoning”, it may be better to design a mechanism that makes &lt;strong&gt;leakage itself worthless&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Onecli, Sigcli, Agent Vault, Ren AI Proxy, and FakeKey each approach this problem from different angles. The tooling landscape in this area is still evolving rapidly, but the direction and value are becoming increasingly clear.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>security</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
