<?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: k-wada</title>
    <description>The latest articles on DEV Community by k-wada (@k-wada).</description>
    <link>https://dev.to/k-wada</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%2F4069023%2F8cbfd45f-fe5f-43e7-9098-3cab0480a40f.png</url>
      <title>DEV Community: k-wada</title>
      <link>https://dev.to/k-wada</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/k-wada"/>
    <language>en</language>
    <item>
      <title>I Went to Numazu and Found an Old Food Technology</title>
      <dc:creator>k-wada</dc:creator>
      <pubDate>Mon, 24 Aug 2026 14:29:59 +0000</pubDate>
      <link>https://dev.to/k-wada/i-went-to-numazu-and-found-an-old-food-technology-nki</link>
      <guid>https://dev.to/k-wada/i-went-to-numazu-and-found-an-old-food-technology-nki</guid>
      <description>&lt;p&gt;Today, no AI.&lt;br&gt;
No code.&lt;/p&gt;

&lt;p&gt;Just fish.&lt;/p&gt;

&lt;p&gt;A few days ago, I took a short trip to &lt;strong&gt;Numazu&lt;/strong&gt;, a coastal city in Shizuoka, Japan.&lt;/p&gt;

&lt;p&gt;Numazu is one of those places where fish feels very close to everyday life.&lt;/p&gt;

&lt;p&gt;You walk around, see the harbor, seafood restaurants, fish shops — and eventually, you get hungry.&lt;/p&gt;

&lt;p&gt;So I did what seemed like the obvious thing.&lt;/p&gt;

&lt;p&gt;I ate fish.&lt;/p&gt;

&lt;p&gt;More specifically:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aji no himono — dried horse mackerel.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It looked very simple.&lt;/p&gt;

&lt;p&gt;A grilled fish, opened flat, with rice and grated daikon radish.&lt;/p&gt;

&lt;p&gt;But while eating it, I started thinking:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This is actually technology.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is himono?
&lt;/h2&gt;

&lt;p&gt;“Himono” literally means dried food, but in everyday Japanese it often refers to dried fish.&lt;/p&gt;

&lt;p&gt;For aji no himono, the fish is usually opened, salted, dried, and then grilled before eating.&lt;/p&gt;

&lt;p&gt;That's basically it.&lt;/p&gt;

&lt;p&gt;No complicated sauce.&lt;/p&gt;

&lt;p&gt;No long list of ingredients.&lt;/p&gt;

&lt;p&gt;Fish.&lt;br&gt;
Salt.&lt;br&gt;
Air.&lt;br&gt;
Time.&lt;/p&gt;

&lt;p&gt;But that simplicity hides a surprisingly clever process.&lt;/p&gt;

&lt;h2&gt;
  
  
  The original problem: fish doesn't keep well
&lt;/h2&gt;

&lt;p&gt;Fresh fish contains a lot of water.&lt;/p&gt;

&lt;p&gt;That's one of the reasons it tastes good.&lt;/p&gt;

&lt;p&gt;It's also one of the reasons it spoils quickly.&lt;/p&gt;

&lt;p&gt;Today, we have refrigerators and freezers.&lt;/p&gt;

&lt;p&gt;People in the past didn't.&lt;/p&gt;

&lt;p&gt;So they needed another solution.&lt;/p&gt;

&lt;p&gt;One answer was simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remove some of the water.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Drying lowers the amount of water available for microorganisms and slows deterioration.&lt;/p&gt;

&lt;p&gt;In modern food science, this is related to the concept of &lt;strong&gt;water activity&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So himono is not just “fish left outside.”&lt;/p&gt;

&lt;p&gt;It is a method of controlling water.&lt;/p&gt;

&lt;p&gt;And that changes everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  It's really a tuning problem
&lt;/h2&gt;

&lt;p&gt;The interesting part is that you don't want to remove all the water.&lt;/p&gt;

&lt;p&gt;Dry too little, and preservation doesn't improve enough.&lt;/p&gt;

&lt;p&gt;Dry too much, and the fish becomes hard and unpleasant.&lt;/p&gt;

&lt;p&gt;So you're balancing several things at once:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;preservation&lt;/li&gt;
&lt;li&gt;moisture&lt;/li&gt;
&lt;li&gt;texture&lt;/li&gt;
&lt;li&gt;saltiness&lt;/li&gt;
&lt;li&gt;flavor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That sounds familiar.&lt;/p&gt;

&lt;p&gt;It's a trade-off.&lt;/p&gt;

&lt;p&gt;You could almost describe himono as an old optimization problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preserve the fish, but keep it delicious.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;People solved that problem hundreds of years before anyone called it engineering.&lt;/p&gt;

&lt;h2&gt;
  
  
  Salt isn't just seasoning
&lt;/h2&gt;

&lt;p&gt;Salt also plays more than one role.&lt;/p&gt;

&lt;p&gt;Of course it makes the fish taste good.&lt;/p&gt;

&lt;p&gt;But it also helps draw water from the fish and changes the environment in which microorganisms can grow.&lt;/p&gt;

&lt;p&gt;So salt is not just a topping.&lt;/p&gt;

&lt;p&gt;It's part of the process.&lt;/p&gt;

&lt;p&gt;The recipe is closer to this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Fish + salt + controlled drying + time&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And after that process, the fish is no longer quite the same food.&lt;/p&gt;

&lt;p&gt;The texture changes.&lt;/p&gt;

&lt;p&gt;The aroma changes.&lt;/p&gt;

&lt;p&gt;And the flavor changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then there is umami
&lt;/h2&gt;

&lt;p&gt;This is where Japanese food gets especially interesting.&lt;/p&gt;

&lt;p&gt;The Japanese word &lt;strong&gt;umami&lt;/strong&gt; is now widely used around the world.&lt;/p&gt;

&lt;p&gt;It is generally described as the fifth basic taste, alongside sweet, sour, salty, and bitter.&lt;/p&gt;

&lt;p&gt;Fish naturally contains compounds connected to umami, including glutamate and nucleotides such as inosinate.&lt;/p&gt;

&lt;p&gt;And an important point is this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drying doesn't magically create umami from nothing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's more subtle than that.&lt;/p&gt;

&lt;p&gt;By reducing water, adding salt, changing texture, and allowing biochemical changes during processing, the experience of the flavor becomes different.&lt;/p&gt;

&lt;p&gt;The taste feels deeper.&lt;/p&gt;

&lt;p&gt;More concentrated.&lt;/p&gt;

&lt;p&gt;More satisfying.&lt;/p&gt;

&lt;p&gt;And that's one of the things I noticed while eating the fish in Numazu.&lt;/p&gt;

&lt;p&gt;There wasn't much on the plate.&lt;/p&gt;

&lt;p&gt;But it didn't feel simple at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Maybe that's why I like Japanese food
&lt;/h2&gt;

&lt;p&gt;When people think of Japanese food, they often think of sushi.&lt;/p&gt;

&lt;p&gt;Or ramen.&lt;/p&gt;

&lt;p&gt;Those are great.&lt;/p&gt;

&lt;p&gt;But some of the foods I like most are much less spectacular.&lt;/p&gt;

&lt;p&gt;Grilled fish.&lt;/p&gt;

&lt;p&gt;Rice.&lt;/p&gt;

&lt;p&gt;Miso soup.&lt;/p&gt;

&lt;p&gt;Pickles.&lt;/p&gt;

&lt;p&gt;A little grated daikon.&lt;/p&gt;

&lt;p&gt;Nothing flashy.&lt;/p&gt;

&lt;p&gt;And yet, behind something as ordinary as a piece of dried fish is a long history of people experimenting with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;water, salt, time, temperature, texture, and taste.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's engineering.&lt;/p&gt;

&lt;p&gt;Just not the kind we usually write about on DEV.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small discovery in Numazu
&lt;/h2&gt;

&lt;p&gt;I went to Numazu just expecting a short trip and some good food.&lt;/p&gt;

&lt;p&gt;I came back thinking about dehydration, preservation, and umami.&lt;/p&gt;

&lt;p&gt;That might be an occupational hazard of being an engineer.&lt;/p&gt;

&lt;p&gt;But I like finding technology in ordinary things.&lt;/p&gt;

&lt;p&gt;And himono is a good example.&lt;/p&gt;

&lt;p&gt;It looks like a simple grilled fish.&lt;/p&gt;

&lt;p&gt;But behind it is an old idea:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Control water, and you can control preservation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then keep improving the process until preservation and deliciousness can coexist.&lt;/p&gt;

&lt;p&gt;Humans have been optimizing systems for a very long time.&lt;/p&gt;

&lt;p&gt;Some of them just happen to be edible.&lt;/p&gt;

&lt;p&gt;So if you ever visit Japan, try sushi.&lt;/p&gt;

&lt;p&gt;Try ramen.&lt;/p&gt;

&lt;p&gt;But if you find yourself somewhere like Numazu, look for something simpler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Aji no himono.&lt;/strong&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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F56os8dbr5gf61v66r38v.jpg" 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%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F56os8dbr5gf61v66r38v.jpg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might be eating a small piece of Japanese food engineering.&lt;/p&gt;

</description>
      <category>japan</category>
      <category>watercooler</category>
      <category>food</category>
      <category>technology</category>
    </item>
    <item>
      <title>8 Shipped Chrome Extensions, 4 Ways to Declare Host Permissions</title>
      <dc:creator>k-wada</dc:creator>
      <pubDate>Fri, 21 Aug 2026 17:16:55 +0000</pubDate>
      <link>https://dev.to/k-wada/8-shipped-chrome-extensions-4-ways-to-declare-host-permissions-3n1c</link>
      <guid>https://dev.to/k-wada/8-shipped-chrome-extensions-4-ways-to-declare-host-permissions-3n1c</guid>
      <description>&lt;p&gt;I ship eight small Chrome extensions under Legacy Tools. They are all&lt;br&gt;
Manifest V3, and they all need some form of access to the pages you&lt;br&gt;
visit — that is what tools that check things before you send them do.&lt;/p&gt;

&lt;p&gt;I have written before about &lt;a href="https://dev.to/k-wada/after-shipping-8-chrome-extensions-these-are-the-5-rules-i-always-give-ai-agents-13al"&gt;the rules I give AI agents&lt;/a&gt;&lt;br&gt;
so they never broaden permissions on their own. This post is about the&lt;br&gt;
other side of that: the shapes the declarations themselves take.&lt;br&gt;
Recently I put all eight manifests side by side (the versions shipped to&lt;br&gt;
the Chrome Web Store as of 2026-08-22) and realized they ended up using&lt;br&gt;
four different shapes to declare that access. None of this was planned&lt;br&gt;
up front; each shape fell out of what the tool is. Here is the survey.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four shapes
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Everywhere, all the time — five extensions.&lt;/strong&gt;&lt;br&gt;
Safe Privacy Gate, Safe Attachment Check, Safe Mail Link Check, Site&lt;br&gt;
Operator Check, Find My Age. These step in right before a send or a&lt;br&gt;
click, and there is no way to know in advance which site that will&lt;br&gt;
happen on. Interesting detail: only two of the five actually write&lt;br&gt;
&lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt; into &lt;code&gt;host_permissions&lt;/code&gt;. The other three get the same&lt;br&gt;
breadth from &lt;code&gt;content_scripts.matches&lt;/code&gt; alone.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. One fixed site — one extension.&lt;/strong&gt;&lt;br&gt;
Safe Night Check is a Gmail-only tool, so the whole declaration is a&lt;br&gt;
single pattern: &lt;code&gt;https://mail.google.com/*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. A fixed list plus optional grants — one extension.&lt;/strong&gt;&lt;br&gt;
Safe Privacy Mask enumerates thirty &lt;code&gt;matches&lt;/code&gt; patterns for the AI chat&lt;br&gt;
sites it supports, and puts &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt; into&lt;br&gt;
&lt;code&gt;optional_host_permissions&lt;/code&gt; so that any other site is granted only when&lt;br&gt;
the user adds it, one prompt at a time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. &lt;code&gt;activeTab&lt;/code&gt; only — one extension.&lt;/strong&gt;&lt;br&gt;
Copy &amp;amp; Prep ships no content script at all. It touches only the tab&lt;br&gt;
where you just ran its context-menu action. Standing access: zero.&lt;/p&gt;

&lt;h2&gt;
  
  
  The part that surprised me
&lt;/h2&gt;

&lt;p&gt;While checking what these declarations look like from the user's side&lt;br&gt;
(on &lt;code&gt;chrome://extensions&lt;/code&gt;, with the extensions side-loaded into&lt;br&gt;
Chromium), two things stood out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Permissions section came up empty every time.&lt;/strong&gt; I measured
seven of the eight this way. Between them they use &lt;code&gt;storage&lt;/code&gt;,
&lt;code&gt;scripting&lt;/code&gt;, &lt;code&gt;contextMenus&lt;/code&gt; and &lt;code&gt;activeTab&lt;/code&gt; — none of those produces
a line in that box. "The permissions list is blank, so it must be
harmless" is not a read you can make.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;matches&lt;/code&gt; counts as a host permission.&lt;/strong&gt; Safe Attachment Check
declares no &lt;code&gt;host_permissions&lt;/code&gt; at all, and its site-access wording
was character-for-character identical to Safe Privacy Gate, which
declares &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt; explicitly. You cannot shrink the warning by
moving breadth out of &lt;code&gt;host_permissions&lt;/code&gt; and into &lt;code&gt;content_scripts&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Bonus: the list shown to users is deduplicated. Mask declares thirty
patterns; the screen shows fifteen. A short list does not mean narrow
coverage.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I take from this
&lt;/h2&gt;

&lt;p&gt;Permission declarations are not configuration. They are UI — shown to&lt;br&gt;
the user, in their words, at install time and on the details page. The&lt;br&gt;
shape you choose is a product decision: &lt;code&gt;&amp;lt;all_urls&amp;gt;&lt;/code&gt; is honest for a&lt;br&gt;
tool that must work everywhere, a fixed list is honest for a&lt;br&gt;
single-site tool, and &lt;code&gt;activeTab&lt;/code&gt; is worth the extra design work when&lt;br&gt;
"only when I ask" is the actual contract.&lt;/p&gt;

&lt;p&gt;I wrote up the longer versions of both halves of this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The structure side — what runs where in a Manifest V3 extension, and
how the manifest keys relate:
&lt;a href="https://legacy-tools.dev/en/notes/how-a-chrome-extension-works-manifest-v3/" rel="noopener noreferrer"&gt;https://legacy-tools.dev/en/notes/how-a-chrome-extension-works-manifest-v3/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;The display side — what the Permissions and Site access sections
actually show, measured against our own manifests:
&lt;a href="https://legacy-tools.dev/en/notes/reading-chrome-extension-permissions/" rel="noopener noreferrer"&gt;https://legacy-tools.dev/en/notes/reading-chrome-extension-permissions/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>chromeextension</category>
      <category>webdev</category>
      <category>privacy</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>Running LM Studio Locally Doesn't Mean It Never Connects Out</title>
      <dc:creator>k-wada</dc:creator>
      <pubDate>Thu, 20 Aug 2026 07:01:51 +0000</pubDate>
      <link>https://dev.to/k-wada/running-lm-studio-locally-doesnt-mean-it-never-connects-out-keb</link>
      <guid>https://dev.to/k-wada/running-lm-studio-locally-doesnt-mean-it-never-connects-out-keb</guid>
      <description>&lt;p&gt;When we say &lt;strong&gt;“local LLM,”&lt;/strong&gt; it is easy to mentally translate that into:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Everything stays inside the PC.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For inference, that can be true.&lt;/p&gt;

&lt;p&gt;But the application running the model is still an application with network-capable features.&lt;/p&gt;

&lt;p&gt;LM Studio, for example, may need connectivity for things such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;searching for models&lt;/li&gt;
&lt;li&gt;downloading models&lt;/li&gt;
&lt;li&gt;downloading runtimes&lt;/li&gt;
&lt;li&gt;checking for application updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It can also expose a local API server, connect to MCP servers, enable CORS, or serve the API to other devices on the LAN.&lt;/p&gt;

&lt;p&gt;None of those features are inherently bad.&lt;/p&gt;

&lt;p&gt;But I wanted a much narrower environment:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;one approved model, local inference, and as little external connectivity as possible.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I treated “local execution” and “network isolation” as two separate problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  My target state
&lt;/h2&gt;

&lt;p&gt;For normal use, I wanted this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LM Studio
   |
   +---- 127.0.0.1 / localhost ---- allowed
   |
   +---- LAN ----------------------- blocked
   |
   +---- Internet ------------------ blocked
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is the loopback connection.&lt;/p&gt;

&lt;p&gt;Blocking everything blindly can also break communication that stays entirely inside the machine.&lt;/p&gt;

&lt;p&gt;So the rule became:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;deny external communication, but deliberately preserve loopback.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration is not the security boundary
&lt;/h2&gt;

&lt;p&gt;LM Studio already provides useful settings.&lt;/p&gt;

&lt;p&gt;For my baseline I disable features I do not need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serve on Local Network&lt;/li&gt;
&lt;li&gt;CORS&lt;/li&gt;
&lt;li&gt;per-request MCP&lt;/li&gt;
&lt;li&gt;MCP servers from &lt;code&gt;mcp.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cloud features / web search&lt;/li&gt;
&lt;li&gt;automatic model switching or unexpected model loading&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also keep the API server off because I do not need it for this evaluation.&lt;/p&gt;

&lt;p&gt;And my &lt;code&gt;mcp.json&lt;/code&gt; is intentionally boring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I do not want the security of the environment to depend entirely on application settings.&lt;/p&gt;

&lt;p&gt;Settings can be changed.&lt;/p&gt;

&lt;p&gt;Their internal representation can also change between versions.&lt;/p&gt;

&lt;p&gt;So I use two layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LM Studio settings
        +
OS network controls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first expresses the intended configuration.&lt;/p&gt;

&lt;p&gt;The second enforces the boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate setup from normal use
&lt;/h2&gt;

&lt;p&gt;This was probably the most useful design decision.&lt;/p&gt;

&lt;p&gt;LM Studio needs the network while preparing the machine.&lt;/p&gt;

&lt;p&gt;So I split operation into two phases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup phase
&lt;/h3&gt;

&lt;p&gt;Network access is temporarily available for things that genuinely require it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install LM Studio
        ↓
Download the approved runtime
        ↓
Download the approved model
        ↓
Verify the files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, normal use does not need model discovery or downloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Normal-use phase
&lt;/h3&gt;

&lt;p&gt;The environment becomes much smaller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start LM Studio
        ↓
Restore the hardened configuration
        ↓
Check MCP configuration
        ↓
Check network restrictions
        ↓
Unload previously loaded models
        ↓
Load only the approved model
        ↓
Run locally
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This avoids trying to make installation and daily operation obey the same network policy.&lt;/p&gt;

&lt;p&gt;They are different states.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pin the model at startup
&lt;/h2&gt;

&lt;p&gt;Another thing I did not want was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“LM Studio is approved, therefore any model inside LM Studio is approved.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are two different decisions.&lt;/p&gt;

&lt;p&gt;At startup I first unload existing models:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lms unload &lt;span class="nt"&gt;--all&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I load the model selected for the evaluation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lms load &amp;lt;approved-model&amp;gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--context-length&lt;/span&gt; 8192 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--identifier&lt;/span&gt; approved-model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual startup wrapper also verifies that the expected model is available before continuing.&lt;/p&gt;

&lt;p&gt;If the expected state cannot be established, startup should fail rather than quietly falling back to something else.&lt;/p&gt;

&lt;p&gt;That is a small change, but it makes the environment much more reproducible.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you need the API server
&lt;/h2&gt;

&lt;p&gt;My current use case does not require it, so I leave it off.&lt;/p&gt;

&lt;p&gt;But LM Studio's CLI supports explicitly binding the server to loopback:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lms server start &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--bind&lt;/span&gt; 127.0.0.1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--port&lt;/span&gt; 1234
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is very different from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lms server start &lt;span class="nt"&gt;--bind&lt;/span&gt; 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first stays on localhost.&lt;/p&gt;

&lt;p&gt;The second makes the server reachable beyond localhost and changes the security boundary significantly.&lt;/p&gt;

&lt;p&gt;For a controlled local evaluation, I would not expose it unless there is a concrete reason to do so.&lt;/p&gt;

&lt;h2&gt;
  
  
  I also verify the result
&lt;/h2&gt;

&lt;p&gt;A configuration file saying “disabled” is not enough.&lt;/p&gt;

&lt;p&gt;I want to observe what actually happens.&lt;/p&gt;

&lt;p&gt;So the evaluation includes checks such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which processes are listening on ports&lt;/li&gt;
&lt;li&gt;whether unexpected external connections appear&lt;/li&gt;
&lt;li&gt;whether the API server is running&lt;/li&gt;
&lt;li&gt;whether MCP configuration changed&lt;/li&gt;
&lt;li&gt;which model is actually loaded&lt;/li&gt;
&lt;li&gt;whether unexpected GGUF files appeared&lt;/li&gt;
&lt;li&gt;whether firewall rules are still present&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The distinction matters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;configuration → what should happen
verification  → what actually happened
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this kind of environment, I want both.&lt;/p&gt;

&lt;h2&gt;
  
  
  “Local” describes where inference happens
&lt;/h2&gt;

&lt;p&gt;This experiment changed how I think about the word &lt;strong&gt;local&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A local LLM tells me where the model inference runs.&lt;/p&gt;

&lt;p&gt;It does not automatically define every network behavior of the application surrounding that model.&lt;/p&gt;

&lt;p&gt;So my final model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Local inference
      ≠
Network isolation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I care about both, I need to design for both.&lt;/p&gt;

&lt;p&gt;LM Studio already works well offline once the required model and runtime are available.&lt;/p&gt;

&lt;p&gt;What I added was a smaller operational boundary around it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;prepare while connected, then run with the outside closed and only the communication that must stay inside the machine deliberately preserved.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The full implementation and notes are available in the original Legacy Tools article.&lt;/p&gt;

</description>
      <category>lmstudio</category>
      <category>security</category>
      <category>llm</category>
      <category>hardning</category>
    </item>
    <item>
      <title>I Asked AI for Chrome Extension Ideas. It Kept Saying “AI Can Already Do That.”</title>
      <dc:creator>k-wada</dc:creator>
      <pubDate>Mon, 17 Aug 2026 13:52:08 +0000</pubDate>
      <link>https://dev.to/k-wada/i-asked-ai-for-chrome-extension-ideas-it-kept-saying-ai-can-already-do-that-2adi</link>
      <guid>https://dev.to/k-wada/i-asked-ai-for-chrome-extension-ideas-it-kept-saying-ai-can-already-do-that-2adi</guid>
      <description>&lt;h1&gt;
  
  
  I Asked AI for Chrome Extension Ideas. It Kept Saying “AI Can Already Do That.”
&lt;/h1&gt;

&lt;p&gt;I’ve been building small Chrome extensions lately.&lt;/p&gt;

&lt;p&gt;And, like many developers, I often ask AI for ideas.&lt;/p&gt;

&lt;p&gt;Something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What small browser problems are still worth solving?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answers are usually reasonable.&lt;/p&gt;

&lt;p&gt;But there’s one response I keep running into.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;“You can already do that with AI.”&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Need to summarize some text?&lt;br&gt;
AI can do it.&lt;/p&gt;

&lt;p&gt;Need to clean up copied text?&lt;br&gt;
AI can do it.&lt;/p&gt;

&lt;p&gt;Need to compare information from several pages?&lt;br&gt;
AI can do it.&lt;/p&gt;

&lt;p&gt;Need to rewrite something before sending it?&lt;br&gt;
AI can do it.&lt;/p&gt;

&lt;p&gt;Technically, that’s true.&lt;/p&gt;

&lt;p&gt;But after building several small tools, I think it’s also the wrong question.&lt;/p&gt;

&lt;h2&gt;
  
  
  “Can AI do it?” is a very low bar
&lt;/h2&gt;

&lt;p&gt;Almost anything involving text can now be done with an AI chat.&lt;/p&gt;

&lt;p&gt;But that often means:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy something&lt;/li&gt;
&lt;li&gt;Open an AI tool&lt;/li&gt;
&lt;li&gt;Paste it&lt;/li&gt;
&lt;li&gt;Explain what you want&lt;/li&gt;
&lt;li&gt;Check the result&lt;/li&gt;
&lt;li&gt;Copy it again&lt;/li&gt;
&lt;li&gt;Go back to what you were doing&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That works.&lt;/p&gt;

&lt;p&gt;But it’s still a workflow.&lt;/p&gt;

&lt;p&gt;Sometimes a tiny browser extension can turn that into:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;select → click → done&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That difference matters more than I expected.&lt;/p&gt;

&lt;h2&gt;
  
  
  A small example
&lt;/h2&gt;

&lt;p&gt;One of the extensions I built is called &lt;strong&gt;Copy &amp;amp; Prep&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It lets me collect text from multiple pages, reorder it, clean it up, and copy everything together.&lt;/p&gt;

&lt;p&gt;Could I do that with ChatGPT?&lt;/p&gt;

&lt;p&gt;Of course.&lt;/p&gt;

&lt;p&gt;But I don’t actually want to explain the same task to ChatGPT every time.&lt;/p&gt;

&lt;p&gt;I just want the text.&lt;/p&gt;

&lt;p&gt;That made me realize something.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI capability is not the same as product UX
&lt;/h2&gt;

&lt;p&gt;When I ask AI whether an idea is useful, it tends to think in terms of capability.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“This task can already be performed.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Users often think differently.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How many steps does this take?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are not the same question.&lt;/p&gt;

&lt;p&gt;And I think this creates a small opportunity for browser extensions.&lt;/p&gt;

&lt;p&gt;Not to compete with AI.&lt;/p&gt;

&lt;p&gt;But to remove the need to ask AI in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  The question I use now
&lt;/h2&gt;

&lt;p&gt;So when I think about small tool ideas, I’ve stopped asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can AI do this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead, I ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Should the user have to ask AI to do this every time?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is no, there may still be a useful little tool hiding there.&lt;/p&gt;

&lt;p&gt;And honestly, I find those small tools much more interesting to build.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>webdev</category>
      <category>chromeextension</category>
      <category>ai</category>
    </item>
    <item>
      <title>Chrome Web Store Rejected My Extension for “Keyword Spam” — Here’s What I Changed</title>
      <dc:creator>k-wada</dc:creator>
      <pubDate>Thu, 13 Aug 2026 12:45:08 +0000</pubDate>
      <link>https://dev.to/k-wada/chrome-web-store-rejected-my-extension-for-keyword-spam-heres-what-i-changed-18i4</link>
      <guid>https://dev.to/k-wada/chrome-web-store-rejected-my-extension-for-keyword-spam-heres-what-i-changed-18i4</guid>
      <description>&lt;h1&gt;
  
  
  I recently submitted a Chrome extension to the Chrome Web Store and got a rejection I wasn't expecting:
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Keyword Spam.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The extension itself worked.&lt;/p&gt;

&lt;p&gt;Its permissions were intentionally limited.&lt;/p&gt;

&lt;p&gt;It didn't send user data to an external server.&lt;/p&gt;

&lt;p&gt;The problem wasn't the code.&lt;/p&gt;

&lt;p&gt;It was the store listing.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Was Trying to Make the Extension Easy to Find
&lt;/h2&gt;

&lt;p&gt;When you publish a Chrome extension, you have to write several pieces of text:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the extension name&lt;/li&gt;
&lt;li&gt;a short description&lt;/li&gt;
&lt;li&gt;a detailed description&lt;/li&gt;
&lt;li&gt;feature explanations&lt;/li&gt;
&lt;li&gt;privacy-related information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Naturally, you want people to understand what the extension does.&lt;/p&gt;

&lt;p&gt;And you also want them to find it.&lt;/p&gt;

&lt;p&gt;That's where I made a mistake.&lt;/p&gt;

&lt;p&gt;I had repeated similar words and phrases across the listing because they accurately described the extension.&lt;/p&gt;

&lt;p&gt;From my perspective, I was being explicit.&lt;/p&gt;

&lt;p&gt;From the Chrome Web Store's perspective, the listing apparently looked too much like keyword stuffing.&lt;/p&gt;

&lt;p&gt;The submission was rejected.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Description Is Not Always Better
&lt;/h2&gt;

&lt;p&gt;This was useful because it changed how I think about Chrome Web Store listings.&lt;/p&gt;

&lt;p&gt;A product page is not a normal SEO article.&lt;/p&gt;

&lt;p&gt;When writing an article, it can make sense to explain a topic using several related terms.&lt;/p&gt;

&lt;p&gt;A store listing has a different job.&lt;/p&gt;

&lt;p&gt;It needs to explain:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What does this extension do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does &lt;strong&gt;not&lt;/strong&gt; need to contain every phrase someone might search for.&lt;/p&gt;

&lt;p&gt;Trying to optimize too aggressively can actually make the listing worse.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Changed
&lt;/h2&gt;

&lt;p&gt;I went back through the listing and removed wording that existed mainly for discoverability.&lt;/p&gt;

&lt;p&gt;Instead of repeating multiple variations of the same concept, I tried to describe each function once, in plain language.&lt;/p&gt;

&lt;p&gt;The basic rule became:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Describe the product, not the search queries you want to rank for.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I also checked whether each sentence helped a person understand the extension.&lt;/p&gt;

&lt;p&gt;If removing a phrase didn't make the product harder to understand, I removed it.&lt;/p&gt;

&lt;p&gt;That made the listing shorter and clearer.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Difficult Part: There Is No Perfect Keyword Density
&lt;/h2&gt;

&lt;p&gt;The rejection also exposed a practical problem.&lt;/p&gt;

&lt;p&gt;There isn't a simple rule like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use a keyword no more than three times.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At least, that isn't a useful way to think about it.&lt;/p&gt;

&lt;p&gt;A description can contain repeated terminology for legitimate reasons. Chrome extensions are often built around a very small number of concepts, so some repetition is unavoidable.&lt;/p&gt;

&lt;p&gt;The better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Would I still write this phrase if search ranking didn't exist?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is no, it probably deserves another look.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store Optimization and SEO Are Different Problems
&lt;/h2&gt;

&lt;p&gt;Before this rejection, I treated the Chrome Web Store listing partly like a small landing page.&lt;/p&gt;

&lt;p&gt;Now I separate the two.&lt;/p&gt;

&lt;p&gt;On my own website, I can write detailed articles around problems users may search for.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to check information before sending it&lt;/li&gt;
&lt;li&gt;how to inspect PDF metadata&lt;/li&gt;
&lt;li&gt;how to build a Chrome extension&lt;/li&gt;
&lt;li&gt;mistakes I made during Chrome Web Store review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those pages can provide context and answer broader questions.&lt;/p&gt;

&lt;p&gt;The Chrome Web Store listing can stay focused on the extension itself.&lt;/p&gt;

&lt;p&gt;That division is much cleaner.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;Publishing a Chrome extension involves more than getting &lt;code&gt;manifest.json&lt;/code&gt; right.&lt;/p&gt;

&lt;p&gt;The listing itself is part of the product.&lt;/p&gt;

&lt;p&gt;After this rejection, my approach is now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Explain exactly what the extension does.&lt;/li&gt;
&lt;li&gt;Avoid unnecessary synonyms and repeated search phrases.&lt;/li&gt;
&lt;li&gt;Keep the description readable for humans.&lt;/li&gt;
&lt;li&gt;Put broader explanatory and search-oriented content on my own site.&lt;/li&gt;
&lt;li&gt;Treat Chrome Web Store review feedback as product feedback, not just a hurdle to get past.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It was a small rejection, but a useful one.&lt;/p&gt;

&lt;p&gt;Building the extension was not the part that caused the problem.&lt;/p&gt;

&lt;p&gt;Trying too hard to help people find it was.&lt;/p&gt;

</description>
      <category>chromeextension</category>
      <category>webdev</category>
      <category>productivity</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>I Published a Chrome Extension — Then Found My Home Address on the Store Page</title>
      <dc:creator>k-wada</dc:creator>
      <pubDate>Tue, 11 Aug 2026 06:50:16 +0000</pubDate>
      <link>https://dev.to/k-wada/i-published-a-chrome-extension-then-found-my-home-address-on-the-store-page-3pg2</link>
      <guid>https://dev.to/k-wada/i-published-a-chrome-extension-then-found-my-home-address-on-the-store-page-3pg2</guid>
      <description>&lt;p&gt;After publishing one of my Chrome extensions, I opened its Chrome Web Store page to check how everything looked.&lt;/p&gt;

&lt;p&gt;The description was there.&lt;br&gt;
The screenshots looked fine.&lt;br&gt;
The listing was live.&lt;/p&gt;

&lt;p&gt;Then I scrolled down.&lt;/p&gt;

&lt;p&gt;And saw an address I recognized immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It was my home address.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I had been thinking about the user's privacy, not mine
&lt;/h2&gt;

&lt;p&gt;For the extensions I build under Legacy Tools, I pay a lot of attention to privacy.&lt;/p&gt;

&lt;p&gt;I try to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep processing inside the browser&lt;/li&gt;
&lt;li&gt;avoid unnecessary permissions&lt;/li&gt;
&lt;li&gt;avoid external network requests where possible&lt;/li&gt;
&lt;li&gt;avoid collecting user input or detection results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I had reviewed permissions, data handling, and Chrome Web Store disclosures carefully.&lt;/p&gt;

&lt;p&gt;But I had completely missed another category of information:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;the developer's own information.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I had spent so much time thinking about what my extension might expose that I never seriously checked what publishing the extension might expose about me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reason was my trader status
&lt;/h2&gt;

&lt;p&gt;Chrome Web Store asks developers to declare whether they are acting as a trader or a non-trader.&lt;/p&gt;

&lt;p&gt;When I first completed the registration, I selected the trader option.&lt;/p&gt;

&lt;p&gt;Here, "trader" does not mean someone trading stocks.&lt;/p&gt;

&lt;p&gt;It refers to whether you are acting for purposes related to your trade, business, craft, or profession.&lt;/p&gt;

&lt;p&gt;When I reviewed the information again, I realized that verified contact information associated with a trader can be displayed on the Chrome Web Store.&lt;/p&gt;

&lt;p&gt;I had treated the address as information I was providing to Google for verification.&lt;/p&gt;

&lt;p&gt;I had not understood that it could become information visible to users.&lt;/p&gt;

&lt;p&gt;By the time I noticed, the extension was already public.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Just choose non-trader" is not the lesson
&lt;/h2&gt;

&lt;p&gt;My first reaction was obvious:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Then I should just switch to non-trader.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But that is not really the right way to think about it.&lt;/p&gt;

&lt;p&gt;Trader status is not a privacy toggle.&lt;/p&gt;

&lt;p&gt;You should not choose non-trader simply because you do not want your address to appear.&lt;/p&gt;

&lt;p&gt;The declaration needs to match how you actually operate.&lt;/p&gt;

&lt;p&gt;In my case, I reviewed the description and my current way of publishing Legacy Tools extensions, which are currently offered for free, and concluded that non-trader better matched my situation.&lt;/p&gt;

&lt;p&gt;After I changed the setting, the address was no longer displayed on the store page.&lt;/p&gt;

&lt;p&gt;But the important lesson was not the setting itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer identity is part of product design
&lt;/h2&gt;

&lt;p&gt;Before this happened, I thought of developer registration as an administrative step at the end of the publishing process.&lt;/p&gt;

&lt;p&gt;Build the extension.&lt;/p&gt;

&lt;p&gt;Prepare the screenshots.&lt;/p&gt;

&lt;p&gt;Write the description.&lt;/p&gt;

&lt;p&gt;Pass the review.&lt;/p&gt;

&lt;p&gt;Publish.&lt;/p&gt;

&lt;p&gt;Done.&lt;/p&gt;

&lt;p&gt;That was too simple.&lt;/p&gt;

&lt;p&gt;If you plan to publish extensions as an independent developer, you should think about things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whose name will appear as the publisher&lt;/li&gt;
&lt;li&gt;which address is associated with the developer account&lt;/li&gt;
&lt;li&gt;which email address users will see&lt;/li&gt;
&lt;li&gt;whether you should separate personal and public contact information&lt;/li&gt;
&lt;li&gt;how your trader status affects the information shown to users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of these questions change your JavaScript.&lt;/p&gt;

&lt;p&gt;But they absolutely affect what it means to publish software publicly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Check your own store page after publishing
&lt;/h2&gt;

&lt;p&gt;Once an extension passes review, it is easy to feel that the job is finished.&lt;/p&gt;

&lt;p&gt;I now think there is one more step.&lt;/p&gt;

&lt;p&gt;Open the public Chrome Web Store listing exactly as a user would.&lt;/p&gt;

&lt;p&gt;Scroll from top to bottom.&lt;/p&gt;

&lt;p&gt;Do not only check the screenshots and description.&lt;/p&gt;

&lt;p&gt;Check what information about &lt;strong&gt;you&lt;/strong&gt; is being published alongside the extension.&lt;/p&gt;

&lt;p&gt;I learned this only after finding my own home address on the page.&lt;/p&gt;

&lt;p&gt;Publishing a browser extension is not only about deciding what your software reveals.&lt;/p&gt;

&lt;p&gt;It is also about deciding what &lt;strong&gt;you&lt;/strong&gt;, as the developer, reveal with it.&lt;/p&gt;

</description>
      <category>chromeextension</category>
      <category>privacy</category>
      <category>indiedev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>After Shipping 8 Chrome Extensions, These Are the 5 Rules I Always Give AI Agents</title>
      <dc:creator>k-wada</dc:creator>
      <pubDate>Sat, 08 Aug 2026 17:01:20 +0000</pubDate>
      <link>https://dev.to/k-wada/after-shipping-8-chrome-extensions-these-are-the-5-rules-i-always-give-ai-agents-13al</link>
      <guid>https://dev.to/k-wada/after-shipping-8-chrome-extensions-these-are-the-5-rules-i-always-give-ai-agents-13al</guid>
      <description>&lt;p&gt;AI agents can build Chrome extensions surprisingly fast.&lt;/p&gt;

&lt;p&gt;After shipping eight extensions, though, I found that the biggest risks usually do not come from whether the code runs.&lt;/p&gt;

&lt;p&gt;They come from what the agent quietly adds while trying to be helpful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;another permission&lt;/li&gt;
&lt;li&gt;an external request&lt;/li&gt;
&lt;li&gt;a new dependency&lt;/li&gt;
&lt;li&gt;a refactor I did not ask for&lt;/li&gt;
&lt;li&gt;a change in what user data is read or stored&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of those can affect security, privacy, maintenance, and Chrome Web Store review.&lt;/p&gt;

&lt;p&gt;So before I ask an AI agent to implement anything, I now give it a small set of rules.&lt;/p&gt;

&lt;p&gt;These are the five I use most often.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Do not add or broaden permissions without asking
&lt;/h2&gt;

&lt;p&gt;Chrome extension permissions are part of the product.&lt;/p&gt;

&lt;p&gt;If the agent adds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"storage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"tabs"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or expands &lt;code&gt;host_permissions&lt;/code&gt;, that is not just an implementation detail.&lt;/p&gt;

&lt;p&gt;It changes what the extension is allowed to access and may change what users see during installation or what I need to explain during review.&lt;/p&gt;

&lt;p&gt;So I explicitly tell the agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not add or broaden permissions without asking me first.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If a new permission is necessary, I want the agent to stop and explain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which permission is needed&lt;/li&gt;
&lt;li&gt;why it is needed&lt;/li&gt;
&lt;li&gt;what feature requires it&lt;/li&gt;
&lt;li&gt;whether there is a narrower alternative&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The default should be &lt;strong&gt;minimum permissions&lt;/strong&gt;, not “whatever makes implementation easier.”&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Do not add network communication
&lt;/h2&gt;

&lt;p&gt;A small local extension can easily become something very different if an agent introduces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an external API&lt;/li&gt;
&lt;li&gt;analytics&lt;/li&gt;
&lt;li&gt;telemetry&lt;/li&gt;
&lt;li&gt;a CDN&lt;/li&gt;
&lt;li&gt;remote configuration&lt;/li&gt;
&lt;li&gt;cloud storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes these are useful.&lt;/p&gt;

&lt;p&gt;But they should never appear accidentally.&lt;/p&gt;

&lt;p&gt;For many of my extensions, I deliberately keep the design simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Web page
   ↓
Chrome extension
   ↓
chrome.storage.local
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No server.&lt;/p&gt;

&lt;p&gt;No account.&lt;/p&gt;

&lt;p&gt;No external transmission.&lt;/p&gt;

&lt;p&gt;That makes both the implementation and the privacy story easier to understand.&lt;/p&gt;

&lt;p&gt;So my second rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not add external network requests, analytics, telemetry, or CDN dependencies.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If network access is truly required, I want that to become a design decision before it becomes code.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Do not modify unrelated files or features
&lt;/h2&gt;

&lt;p&gt;This one became more important as I started using coding agents for larger changes.&lt;/p&gt;

&lt;p&gt;Suppose I ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Add a function that stores selected text in chrome.storage.local.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;An agent may notice nearby code and decide to improve it too.&lt;/p&gt;

&lt;p&gt;The result might work.&lt;/p&gt;

&lt;p&gt;But now one small task has changed five files.&lt;/p&gt;

&lt;p&gt;That makes review harder.&lt;/p&gt;

&lt;p&gt;It also becomes difficult to answer a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What exactly changed because of this request?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So I usually add:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not modify unrelated files, features, or architecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For small Chrome extensions, I prefer changes that are easy to understand and easy to reverse.&lt;/p&gt;

&lt;p&gt;I would rather make five small changes than one clever change that touches the entire project.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Do not add dependencies unless they are really necessary
&lt;/h2&gt;

&lt;p&gt;AI agents are very good at finding packages.&lt;/p&gt;

&lt;p&gt;That does not mean I want them.&lt;/p&gt;

&lt;p&gt;If a 20-line utility function can solve the problem, adding another npm dependency may not be worth it.&lt;/p&gt;

&lt;p&gt;Every dependency creates more things to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;supply-chain risk&lt;/li&gt;
&lt;li&gt;updates&lt;/li&gt;
&lt;li&gt;licenses&lt;/li&gt;
&lt;li&gt;bundle size&lt;/li&gt;
&lt;li&gt;build complexity&lt;/li&gt;
&lt;li&gt;future maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not add new dependencies unless they are necessary. If you think one is needed, explain why before adding it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is especially useful for browser extensions because many features can be implemented with the browser APIs and plain JavaScript.&lt;/p&gt;

&lt;p&gt;Small tools benefit from staying small.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Stop before changing the data flow
&lt;/h2&gt;

&lt;p&gt;This is the most important rule.&lt;/p&gt;

&lt;p&gt;If an implementation changes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what data is read&lt;/li&gt;
&lt;li&gt;where data is stored&lt;/li&gt;
&lt;li&gt;how long it is stored&lt;/li&gt;
&lt;li&gt;whether data leaves the browser&lt;/li&gt;
&lt;li&gt;which pages the extension can access&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I do not want the agent to decide that silently.&lt;/p&gt;

&lt;p&gt;I tell it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If your change affects what data is read, stored, or transmitted, stop and explain the change before implementing it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This turns data flow into an explicit design decision.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Selected text
    ↓
Content script
    ↓
chrome.storage.local
    ↓
Extension UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the agent wants to change that into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Selected text
    ↓
Content script
    ↓
External API
    ↓
Extension UI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that is not a small implementation change.&lt;/p&gt;

&lt;p&gt;It is a different product architecture.&lt;/p&gt;

&lt;p&gt;I want to know before the code changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  The prompt I actually reuse
&lt;/h2&gt;

&lt;p&gt;Here is the short version I give coding agents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;When modifying this Chrome extension:

- Do not add or broaden permissions without asking me first.
- Do not add external network requests, analytics, telemetry, or CDN dependencies.
- Do not modify unrelated files or features.
- Do not add new dependencies unless they are necessary.
- If your change affects what data is read, stored, or transmitted, stop and explain the change before implementing it.
- Keep the implementation compatible with Manifest V3.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I usually add the task itself underneath this block.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Task:

Add the ability to save selected text to chrome.storage.local.

Do not change the list UI or reordering behavior.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is that the agent receives both:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;what I want it to do&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;and&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;what it is not allowed to decide on its own.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  I still verify everything myself
&lt;/h2&gt;

&lt;p&gt;These rules reduce surprises.&lt;/p&gt;

&lt;p&gt;They do not replace review.&lt;/p&gt;

&lt;p&gt;Before publishing, I still check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[ ] Are all permissions necessary?
[ ] Did any host permissions become broader?
[ ] Are there unexpected network requests?
[ ] Did the agent add a dependency?
[ ] Do I know exactly what data is read?
[ ] Do I know exactly what data is stored?
[ ] Does any data leave the browser?
[ ] Does the Chrome Web Store declaration match the implementation?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also load the extension through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chrome://extensions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and use it on real pages before submitting it.&lt;/p&gt;

&lt;p&gt;An extension can pass tests and still feel annoying, request too much access, or behave differently from the store description.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changed after eight extensions
&lt;/h2&gt;

&lt;p&gt;AI has definitely made implementation faster for me.&lt;/p&gt;

&lt;p&gt;But after shipping eight Chrome extensions, I spend less time asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can the agent build this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;and more time asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What decisions should the agent not be allowed to make?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That distinction has become one of the most useful parts of my workflow.&lt;/p&gt;

&lt;p&gt;AI agents are good at completing tasks.&lt;/p&gt;

&lt;p&gt;My job is to define the boundaries around those tasks.&lt;/p&gt;

&lt;p&gt;For Chrome extensions, those boundaries are especially important because permissions, network access, dependencies, and data handling affect not only the code, but also what users are being asked to trust.&lt;/p&gt;

&lt;p&gt;I am building and documenting these experiments as part of &lt;strong&gt;Legacy Tools&lt;/strong&gt;, a collection of small browser tools.&lt;/p&gt;

&lt;p&gt;The full development workflow I use — from choosing an idea to Chrome Web Store review — is also available on the Legacy Tools site.&lt;/p&gt;

</description>
      <category>chromeextension</category>
      <category>webdev</category>
      <category>agents</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
