<?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: kaz</title>
    <description>The latest articles on DEV Community by kaz (@kaz123).</description>
    <link>https://dev.to/kaz123</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%2F629464%2F44f1135b-84f7-4d91-8a58-0c224ffaad36.jpg</url>
      <title>DEV Community: kaz</title>
      <link>https://dev.to/kaz123</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kaz123"/>
    <language>en</language>
    <item>
      <title>ADGM Tech Startup License: Self-Filed UAE Entity, $1,000, No Agent</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Wed, 01 Apr 2026 16:12:26 +0000</pubDate>
      <link>https://dev.to/kaz123/adgm-tech-startup-license-self-filed-uae-entity-1000-no-agent-3o0</link>
      <guid>https://dev.to/kaz123/adgm-tech-startup-license-self-filed-uae-entity-1000-no-agent-3o0</guid>
      <description>&lt;p&gt;In 2022, I set up an ADGM Tech Startup License by myself — no CSP, no agent. The registration fee was $1,000. It is now $1,500.&lt;/p&gt;

&lt;p&gt;Most guides assume you will use a CSP (Corporate Service Provider), which adds $3,000–5,000 on top. I skipped it. It worked.&lt;/p&gt;

&lt;p&gt;I also set up a UAE mainland company separately — different purpose, different process. That comparison is worth knowing. (I had a Dubai Virtual Working Program visa at the time and was planning to transfer sponsorship before it expired.)&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.amazonaws.com%2Fuploads%2Farticles%2F51giokqmalv5cxxp3iq4.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.amazonaws.com%2Fuploads%2Farticles%2F51giokqmalv5cxxp3iq4.jpg" alt=" " width="800" height="1066"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where ADGM fits among UAE options
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Cost (approx.)&lt;/th&gt;
&lt;th&gt;Legal framework&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ADGM Tech Startup&lt;/td&gt;
&lt;td&gt;$1,500 + misc&lt;/td&gt;
&lt;td&gt;English common law&lt;/td&gt;
&lt;td&gt;Self-filing possible; Hub71 accepted companies must incorporate here&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DIFC&lt;/td&gt;
&lt;td&gt;$10,000+&lt;/td&gt;
&lt;td&gt;English common law&lt;/td&gt;
&lt;td&gt;Finance-focused, expensive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dubai free zones (DMCC, IFZA etc.)&lt;/td&gt;
&lt;td&gt;$3,000–8,000&lt;/td&gt;
&lt;td&gt;UAE civil law&lt;/td&gt;
&lt;td&gt;Wide variety, Dubai address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;RAKEZ&lt;/td&gt;
&lt;td&gt;$1,500–5,500&lt;/td&gt;
&lt;td&gt;UAE civil law&lt;/td&gt;
&lt;td&gt;Cheapest, less prestige&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mainland&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;UAE civil law&lt;/td&gt;
&lt;td&gt;CSP typically required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;My reason for ADGM over Dubai free zones: cheapest English common law entity, and it keeps the Hub71 path open. You can apply to Hub71 before incorporating — no entity required to apply. If accepted, you incorporate in ADGM as part of joining, and the voucher covers CSP and other costs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On RAKEZ&lt;/strong&gt;: I have no personal experience. Based on research: mostly online incorporation with one UAE visit required for visa biometrics (doable in Dubai, not necessarily in RAK itself), banking accessible but may face more scrutiny at international banks, disputes go through RAK Commercial Court. Worth considering for cost-focused operational startups with no complex legal needs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;On mainland&lt;/strong&gt;: I set one up to transfer my visa sponsorship before my nomad visa expired. Did not end up needing it, so I closed it. CSP was involved, banking through ADCB. The 2021 reform allowing 100% foreign ownership removed the local sponsor requirement — mainland is now a real option for foreign founders in most sectors.&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.amazonaws.com%2Fuploads%2Farticles%2Ffdpbrvtya35jm66clz4w.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.amazonaws.com%2Fuploads%2Farticles%2Ffdpbrvtya35jm66clz4w.jpg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it costs
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Registration fee&lt;/td&gt;
&lt;td&gt;$1,500 (was $1,000 in 2022)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Administrative / misc fees&lt;/td&gt;
&lt;td&gt;~a few hundred USD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSP fee (optional)&lt;/td&gt;
&lt;td&gt;$3,000–5,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Registered office (required)&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If you come through Hub71, the voucher covers the CSP fee and other costs — see the Hub71 section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before You File
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Contact ADGM first.&lt;/strong&gt; Before filing, reach out to confirm the Tech Startup License fits your business activities. The review is not strict, but getting confirmation upfront means you can proceed without uncertainty.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Registered office address.&lt;/strong&gt; I needed a physical address before I could incorporate. (This was 2022 — current requirements may differ.) ADGM's own co-working space had a wait, WeWork on Al Maryah had a wait. Other options existed — CloudSpace (as of 2022) and similar providers. More choices now that Al Reem Island is under ADGM jurisdiction (since December 2024).&lt;/p&gt;

&lt;h2&gt;
  
  
  Banking
&lt;/h2&gt;

&lt;p&gt;I used Mashreq. Direct bank contact, dedicated officer assigned, documents submitted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wio Bank&lt;/strong&gt; is the easiest option now — fully online, built for SMEs. A founder I know used it for a recent incorporation with no issues.&lt;/p&gt;

&lt;p&gt;Hub71 route: &lt;strong&gt;FAB (First Abu Dhabi Bank)&lt;/strong&gt; is a natural starting point — Hub71 has partnerships with FAB, ADCB, and ADNIC (insurance), among others.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visa options
&lt;/h2&gt;

&lt;p&gt;Main visa options for UAE residency as a founder:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Dubai Virtual Working Program visa&lt;/strong&gt; (Virtual Working Visa): a few hundred dollars, proof of overseas income needed. Good for establishing residency before or during incorporation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Company-sponsored visa&lt;/strong&gt;: once the ADGM entity is set up, it can sponsor your visa.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Golden Visa (10-year)&lt;/strong&gt;: several pathways — Hub71 participation, qualifying profession/salary threshold, or real estate investment above AED 2M.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hub71: Apply Before or After Incorporating?
&lt;/h2&gt;

&lt;p&gt;Hub71 (hub71.com) is Abu Dhabi's startup program backed by Mubadala and G42 — office space, funding access, and corporate partnerships for accepted companies. If accepted, the voucher covers incorporation, legal, accounting, and other operational costs.&lt;/p&gt;

&lt;p&gt;You do not need to incorporate before applying — Hub71 accepts applications before you have an entity. But admission takes months, so waiting on a decision can delay operations by half a year or more.&lt;/p&gt;

&lt;p&gt;If you incorporate first, the $1,500 registration fee is self-funded. But the Hub71 voucher still applies to accounting, legal, office costs, and other operational expenses — not just incorporation. Incorporating first does not make Hub71 pointless.&lt;/p&gt;

&lt;p&gt;The practical split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Early stage, time to spare&lt;/strong&gt;: apply first (free). If accepted, the voucher covers incorporation plus operational costs. If not, self-file for $1,500.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Already moving&lt;/strong&gt;: incorporate now and apply in parallel. If accepted, use the voucher for accounting, legal, and office expenses.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your startup fits their focus areas (AI, deep tech, fintech, climate), applying is worth doing regardless of where you are in the process.&lt;/p&gt;

&lt;p&gt;One additional angle for 2026: the security situation around Abu Dhabi has reduced inbound interest from some international founders. If that continues, Hub71's applicant pool may thin — which could improve odds for those applying now.&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.amazonaws.com%2Fuploads%2Farticles%2F7hybv3rvib331pi202ig.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.amazonaws.com%2Fuploads%2Farticles%2F7hybv3rvib331pi202ig.jpg" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What has changed since 2022
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fee: $1,000 → $1,500&lt;/li&gt;
&lt;li&gt;Office options: Al Reem Island under ADGM — more eligible co-working spaces&lt;/li&gt;
&lt;li&gt;Mainland: 100% foreign ownership now standard in most sectors&lt;/li&gt;
&lt;li&gt;Banking: Wio Bank now available, simplest for new incorporations&lt;/li&gt;
&lt;li&gt;Document prep: AI tools make business plans and constitutional docs much faster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Self-filing still works. The process is more accessible now than it was.&lt;/p&gt;

</description>
      <category>startup</category>
      <category>uae</category>
      <category>incorporation</category>
      <category>abudhabi</category>
    </item>
    <item>
      <title>Offline Claude Code on Mac mini M4: llamafile + Safehouse Sandbox</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Sun, 29 Mar 2026 09:10:58 +0000</pubDate>
      <link>https://dev.to/kaz123/offline-claude-code-on-mac-mini-m4-llamafile-safehouse-sandbox-59kj</link>
      <guid>https://dev.to/kaz123/offline-claude-code-on-mac-mini-m4-llamafile-safehouse-sandbox-59kj</guid>
      <description>&lt;p&gt;I run Claude Code on a Mac mini M4 against a local Qwen3-1.7B model via llamafile. No requests leave the machine. No API fees. The model is weaker than Claude, but for exploratory work — trying things, iterating on drafts, quick edits — it is enough.&lt;/p&gt;

&lt;p&gt;The part that required the most thought was not the model. It was making &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; actually safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why offline
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Cost.&lt;/strong&gt; Every Claude Code session hits the Anthropic API. For early-stage work where the direction isn't clear yet, the cost adds up. A local model costs nothing per request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy.&lt;/strong&gt; Some repos I work in contain drafts and notes I don't want leaving the machine. With a local model, nothing leaves.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;Default: two terminals.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Terminal 1: llamafile (Qwen3-1.7B on :8080)
Terminal 2: run-claude.sh (Claude Code inside Safehouse sandbox)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;llamafile has supported the Anthropic Messages API natively since v0.10.0 — you point &lt;code&gt;ANTHROPIC_BASE_URL&lt;/code&gt; directly at it, no proxy needed. Claude Code thinks it's talking to Anthropic. The request never leaves localhost.&lt;/p&gt;

&lt;p&gt;The repo also includes an optional &lt;code&gt;proxy.py&lt;/code&gt; (130 lines, FastAPI + httpx) for debugging — useful if you want to inspect exactly what Claude Code is sending. Skip it if you don't need that visibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  The &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; problem
&lt;/h2&gt;

&lt;p&gt;Claude Code asks for confirmation before every file write and command by default. That's the right call for interactive use.&lt;/p&gt;

&lt;p&gt;For async workflows — sending a task from my phone and coming back to a completed result — it breaks everything. Nothing finishes while you're away.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; disables those prompts. Without something else enforcing limits, that means unrestricted filesystem access.&lt;/p&gt;

&lt;p&gt;The something else is &lt;strong&gt;Safehouse&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Safehouse does
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/nicknisi/safehouse" rel="noopener noreferrer"&gt;Safehouse&lt;/a&gt; is a macOS sandbox wrapper. It enforces access restrictions at the OS (kernel) level, not the application layer.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;run-claude.sh&lt;/code&gt; launches Claude Code inside a Safehouse sandbox scoped to a single directory. Claude Code can freely read and write within that directory. It cannot reach anything outside — other repos, &lt;code&gt;~/.ssh&lt;/code&gt;, system files.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; inside Safehouse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code acts without asking ✓&lt;/li&gt;
&lt;li&gt;It can only act inside the sandbox ✓&lt;/li&gt;
&lt;li&gt;The OS enforces the boundary, not the app ✓&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the combination that makes async use practical without handing over the whole machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  The LiteLLM supply chain attack (March 2026)
&lt;/h2&gt;

&lt;p&gt;On March 24, 2026, LiteLLM versions 1.82.7 and 1.82.8 on PyPI were found to contain a credential stealer. The malicious code ran automatically on Python startup (via a &lt;code&gt;.pth&lt;/code&gt; file) and exfiltrated AWS credentials, GCP auth, GitHub tokens, SSH keys, and crypto wallet files. Available for ~3 hours before PyPI quarantined them. CVSS 9.4. Fixed in 1.82.9.&lt;/p&gt;

&lt;p&gt;Attack vector: threat actor TeamPCP compromised Trivy — the security scanner in LiteLLM's CI/CD pipeline — and used it to obtain PyPI publishing credentials.&lt;/p&gt;

&lt;p&gt;I wasn't using LiteLLM. I mention this not as "I predicted it" but as a data point: a large, active OSS project has a large, active CI/CD pipeline. That's another way in. Keeping dependencies small reduces that exposure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verdict
&lt;/h2&gt;

&lt;p&gt;The offline setup works well for what it's designed for. Qwen3-1.7B is not Claude Sonnet — for complex reasoning or unfamiliar codebases, the quality gap is real. For exploratory work on familiar repos, it's fine.&lt;/p&gt;

&lt;p&gt;The broader recommendation, regardless of the local LLM question: &lt;strong&gt;if you use &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt; for any reason, use an OS-level sandbox to contain it&lt;/strong&gt;. Application-layer restrictions can be worked around. OS-level ones are much harder to escape.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/0xkaz/claude-llamafile-sandbox" rel="noopener noreferrer"&gt;github.com/0xkaz/claude-llamafile-sandbox&lt;/a&gt; — 3 shell scripts, 1 Python file, 1 README.&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>localllm</category>
      <category>security</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Telegram Bridges for Gemini CLI and Codex After Hitting Claude Code Limits</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Sat, 28 Mar 2026 17:30:08 +0000</pubDate>
      <link>https://dev.to/kaz123/telegram-bridges-for-gemini-cli-and-codex-after-hitting-claude-code-limits-3cc1</link>
      <guid>https://dev.to/kaz123/telegram-bridges-for-gemini-cli-and-codex-after-hitting-claude-code-limits-3cc1</guid>
      <description>&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.amazonaws.com%2Fuploads%2Farticles%2F48w8l16movifus59cwmo.png" 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.amazonaws.com%2Fuploads%2Farticles%2F48w8l16movifus59cwmo.png" alt=" " width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Code usage limits forced me into an annoying realization: the thing I had become dependent on was not just the model. It was the workflow.&lt;/p&gt;

&lt;p&gt;Once you get used to sending work to an agent from your phone, waiting for the reply, then sending the next step while you are away from your desk, normal terminal-only usage starts to feel primitive. So instead of waiting for official remote workflows to improve, I built a small Telegram bridge for two tools I already had locally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gemini CLI&lt;/li&gt;
&lt;li&gt;Codex&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a polished platform. It is a local-first workaround. But it brought back the async loop I actually cared about.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem was not "which model"
&lt;/h2&gt;

&lt;p&gt;Claude Code Channels changed how I work on side projects.&lt;/p&gt;

&lt;p&gt;I could be in a cafe, walking outside, or traveling, and still move a repo forward from Telegram. That changes the whole shape of development. You stop thinking "I need to sit down and code now" and start thinking "I can send the next instruction right now and review the result later."&lt;/p&gt;

&lt;p&gt;When I hit usage limits, I did not really want a different chatbot. I wanted that loop back.&lt;/p&gt;

&lt;p&gt;Gemini CLI and Codex were already on my machine. What they did not have was the same remote, async, mobile-friendly interaction model.&lt;/p&gt;

&lt;p&gt;So I built a bridge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The architecture is intentionally boring
&lt;/h2&gt;

&lt;p&gt;The whole thing is small:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a local Node.js process polls the Telegram Bot API&lt;/li&gt;
&lt;li&gt;it accepts prompts from a specific chat&lt;/li&gt;
&lt;li&gt;it runs Gemini CLI or Codex against a local repository&lt;/li&gt;
&lt;li&gt;it sends stdout and stderr back to Telegram&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is basically it.&lt;/p&gt;

&lt;p&gt;I ended up with two integrations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;codex-telegram-integration&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;gemini-telegram-integration_v2&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I published the repo here:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;github.com/0xkaz/codex-gemini-telegram-bridge&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I like this design because it stays easy to inspect. No hosted backend. No extra control plane. No mystery service between Telegram and the machine where the repo already lives.&lt;/p&gt;

&lt;p&gt;For this kind of tool, that matters. The simpler the chain, the easier it is to trust and debug.&lt;/p&gt;

&lt;h2&gt;
  
  
  Session continuity is what makes it useful
&lt;/h2&gt;

&lt;p&gt;The first version could have been a dumb "Telegram to shell" relay. That would have been enough for a quick demo. It would not have been enough for actual use.&lt;/p&gt;

&lt;p&gt;The real requirement was session continuity.&lt;/p&gt;

&lt;p&gt;If I send a follow-up prompt, I do not want the assistant to forget what happened two messages ago. I want it to continue the current session, keep recent context, and move forward from there. Without that, the UX collapses into repetitive setup messages and wasted tokens.&lt;/p&gt;

&lt;p&gt;That turned out to be the difference between "interesting hack" and "something I actually keep using."&lt;/p&gt;

&lt;p&gt;I also made plain non-command messages behave like prompts by default. I did not want to type slash commands every single time. That small choice made the Telegram chat feel much closer to a real agent interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Telegram formatting matters more than I expected
&lt;/h2&gt;

&lt;p&gt;Raw CLI output looks much worse in chat than it does in a terminal.&lt;/p&gt;

&lt;p&gt;That sounds trivial, but it is not. If replies wrap badly, file links are unreadable, or errors dump full stack traces into Telegram, the workflow becomes annoying fast.&lt;/p&gt;

&lt;p&gt;So I added a few quality-of-life features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;typing indicators while the command is running&lt;/li&gt;
&lt;li&gt;session commands like &lt;code&gt;/sessions&lt;/code&gt;, &lt;code&gt;/resume&lt;/code&gt;, and &lt;code&gt;/reset-session&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cleaner error summaries&lt;/li&gt;
&lt;li&gt;cleanup for markdown-style file links&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is glamorous. All of it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gemini quota errors exposed a product problem
&lt;/h2&gt;

&lt;p&gt;One of the most useful failures happened while testing the Gemini side.&lt;/p&gt;

&lt;p&gt;I hit quota exhaustion. That exposed a bad assumption in the bridge: terminal-grade errors are acceptable in a shell, but often terrible in chat. Dumping a raw quota stack trace into Telegram is not useful. It is just noise.&lt;/p&gt;

&lt;p&gt;So I added error summarization instead of forwarding everything blindly.&lt;/p&gt;

&lt;p&gt;That changed how I thought about the bridge. Once a CLI tool starts replying inside Telegram, the output itself becomes part of the UX. A raw stack trace is acceptable in a terminal. In chat, it just feels broken.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this bridge restores
&lt;/h2&gt;

&lt;p&gt;It does not reproduce Claude Code Channels exactly.&lt;/p&gt;

&lt;p&gt;What it does restore is the part I cared about most:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sending prompts from my phone&lt;/li&gt;
&lt;li&gt;letting the machine at home do the work&lt;/li&gt;
&lt;li&gt;reading a useful reply later&lt;/li&gt;
&lt;li&gt;continuing in the same thread without resetting context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For side projects, that is enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would warn people about
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This is a stopgap, not a finished platform.&lt;/li&gt;
&lt;li&gt;You should strictly limit which Telegram chat is allowed to talk to it.&lt;/li&gt;
&lt;li&gt;Destructive actions like commit, push, or deploy need extra care.&lt;/li&gt;
&lt;li&gt;Model quotas still apply, especially on Gemini.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would still take this over being locked back into terminal-only usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I think this category matters
&lt;/h2&gt;

&lt;p&gt;I do think Gemini CLI and Codex will eventually get better official remote workflows. That feels inevitable.&lt;/p&gt;

&lt;p&gt;But "eventually" is not very useful when the workflow break is happening right now.&lt;/p&gt;

&lt;p&gt;This bridge is exactly the kind of engineering I like: not the final version, not especially elegant, but good enough to restore a missing capability immediately.&lt;/p&gt;

&lt;p&gt;If you got used to Claude Code Channels and want something similar for Gemini CLI or Codex today, a local-first Telegram bridge is a surprisingly practical answer.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>telegram</category>
      <category>codex</category>
      <category>gemini</category>
    </item>
    <item>
      <title>UAE Property Investment: Cost Structure, Rental Yield, and Market Signals from Abu Dhabi Under Iran Tensions</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Sat, 28 Mar 2026 09:52:23 +0000</pubDate>
      <link>https://dev.to/kaz123/uae-property-investment-cost-structure-rental-yield-and-market-signals-from-abu-dhabi-under-iran-434b</link>
      <guid>https://dev.to/kaz123/uae-property-investment-cost-structure-rental-yield-and-market-signals-from-abu-dhabi-under-iran-434b</guid>
      <description>&lt;p&gt;&lt;em&gt;Personal analysis based on a single real unit. Not investment advice. Data from direct ownership experience and public market sources. March 2026.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Most discussions around UAE real estate focus on yield.&lt;/p&gt;

&lt;p&gt;However, actual investment performance depends on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cost structure&lt;/li&gt;
&lt;li&gt;vacancy exposure&lt;/li&gt;
&lt;li&gt;macro conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article presents a &lt;strong&gt;single real-unit example&lt;/strong&gt; from Abu Dhabi (Al Reem Island), covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;service charges per sqft&lt;/li&gt;
&lt;li&gt;district cooling structure&lt;/li&gt;
&lt;li&gt;rental benchmarks and yield calculation&lt;/li&gt;
&lt;li&gt;observed market conditions under recent Iran-related tensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not a generalization, but a &lt;strong&gt;data point-based analysis&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Unit Profile
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Location: UAE, Abu Dhabi (Al Reem Island)&lt;/li&gt;
&lt;li&gt;Tower: Sky Tower&lt;/li&gt;
&lt;li&gt;Size: &lt;strong&gt;1,437 sqft (~133 sqm)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Type: 2BR+Maid, 4 Bathrooms&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Cost Structure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Service Charge
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;AED 17,497/year&lt;/li&gt;
&lt;li&gt;~AED &lt;strong&gt;12.2 / sqft&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  District Cooling
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Capacity (fixed)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;~AED 235/month&lt;/li&gt;
&lt;li&gt;~AED 2,800/year&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Usage (variable)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;~AED 50–150/month&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Total Annual Fixed Cost
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;~AED &lt;strong&gt;21,000/year&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;~AED &lt;strong&gt;14.6 / sqft&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Structural Interpretation
&lt;/h2&gt;

&lt;p&gt;Although UAE is often described as "tax-free," these costs function similarly to property tax or infrastructure maintenance levies.&lt;/p&gt;

&lt;p&gt;The service charge and district cooling capacity fee together form a &lt;strong&gt;fixed cost base that does not go away when the unit is vacant&lt;/strong&gt;. This is not a low-cost system — it is a cost-based system instead of a tax-based one. The distinction matters for modeling cash flows.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Rental Benchmarks (Al Reem Island)
&lt;/h2&gt;

&lt;p&gt;Observed range for comparable 2BR units:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~AED &lt;strong&gt;90–120 / sqft&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this 1,437 sqft unit, that translates to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~AED 130K – 170K annual rent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A working midpoint for yield calculations: &lt;strong&gt;AED 150K/year&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Gross vs Net Yield
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Gross Yield
&lt;/h3&gt;

&lt;p&gt;Sky Tower 2BR+Maid (~1,440 sqft) on Al Reem Island: current market price range is approximately &lt;strong&gt;AED 2.3M–2.7M&lt;/strong&gt; (as of early 2026, reflecting the 38% YoY price appreciation recorded in Q2 2025). Observed rent range for comparable units is AED 130K–170K annually. Across these combinations, &lt;strong&gt;gross yield is roughly 5–7%&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Net Yield
&lt;/h3&gt;

&lt;p&gt;After deducting ~AED 21,000 in fixed annual costs, &lt;strong&gt;net yield is roughly 4–6%&lt;/strong&gt; across the plausible range.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Rough range: Gross ~5–7%, Net ~4–6%&lt;/strong&gt; depending on entry price and actual rent achieved.&lt;/p&gt;

&lt;p&gt;This is after fixed costs only — not accounting for agent fees, vacancy, or fit-out amortization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A note on static yield figures:&lt;/strong&gt; Both rent and property prices on Al Reem Island have been rising year-over-year, with prices rising particularly fast (+38% YoY in Q2 2025). From personal experience as an owner on Al Reem Island, asking rent has increased roughly &lt;strong&gt;10–20% per year&lt;/strong&gt; at each tenant turnover in recent years. This means any point-in-time yield calculation is a snapshot — it reflects the relationship between rent and price at a specific moment, not a durable number. Buyers entering at today's prices face different math than those who bought two years ago, and next year's tenants may pay higher rent against a further-appreciated asset. The yield figures here are useful for understanding cost structure, not for predicting returns.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Cost-to-Income Ratio
&lt;/h2&gt;

&lt;p&gt;Fixed costs (~AED 21K) against mid-range rent (AED 150K):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;~&lt;strong&gt;14%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is within global norms for managed residential assets. The ratio is manageable, but only when the unit is occupied.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Vacancy Sensitivity
&lt;/h2&gt;

&lt;p&gt;Even when vacant, the cost structure continues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service charge: continues regardless of occupancy&lt;/li&gt;
&lt;li&gt;Cooling capacity fee: continues regardless of occupancy&lt;/li&gt;
&lt;li&gt;Electricity minimum charges: may apply&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fixed costs create &lt;strong&gt;asymmetric downside&lt;/strong&gt;. Service charge and cooling capacity fees continue regardless of occupancy. A vacant period costs not only the lost rent but also the fixed costs accruing in parallel — more than a simple percentage-of-rent calculation would suggest.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Occupancy Context
&lt;/h2&gt;

&lt;p&gt;Knight Frank's H1 2025 Abu Dhabi Residential Market Review reports Al Reem Island vacancy at approximately &lt;strong&gt;2–3%&lt;/strong&gt; — among the lowest in Abu Dhabi. ADREC publishes broader Abu Dhabi residential occupancy data quarterly.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Geopolitical Context (Iran-related Tensions)
&lt;/h2&gt;

&lt;p&gt;As of March 2026 (observation-based):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No clear change in rental levels&lt;/li&gt;
&lt;li&gt;No visible change in property prices&lt;/li&gt;
&lt;li&gt;Transaction activity appears slower&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;del&gt;Agent inquiries — asking whether the unit was available to rent or buy — dropped from roughly 2 per week before the Iran conflict to roughly 1 per month afterward. This may indicate softening demand, though prices have not yet moved to confirm it.&lt;/del&gt;&lt;/p&gt;

&lt;p&gt;I originally wrote this based on a faulty memory. After checking my records, I've received about six inquiries in March alone.&lt;/p&gt;

&lt;p&gt;This is a &lt;strong&gt;short-term observation&lt;/strong&gt;, not a confirmed trend. Price and inquiry volume can diverge for months before re-converging.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Financial Markets vs Physical Assets
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Real estate equities declined on conflict news&lt;/li&gt;
&lt;li&gt;Physical property prices appear stable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This suggests a possible lag between financial market reactions and real asset pricing. If the conflict extends or escalates, it is not obvious that physical prices remain insulated indefinitely.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Market Outlook
&lt;/h2&gt;

&lt;p&gt;Key variables to watch:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Potential increase in supply (Aldar and Mubadala announced a AED 60B+ expansion of Al Maryah Island's financial district in December 2025)&lt;/li&gt;
&lt;li&gt;Demand sustainability under geopolitical uncertainty&lt;/li&gt;
&lt;li&gt;Prior strong price growth (~38% YoY in Q2 2025) has likely priced in optimistic assumptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A short-term correction would not be unusual given the macro context. The long-term structural case — ADGM jurisdiction, common law framework, government-controlled supply — remains intact.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Conclusion
&lt;/h2&gt;

&lt;p&gt;This example suggests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UAE property carries a structured and predictable fixed cost base (~AED 21K/year for this unit)&lt;/li&gt;
&lt;li&gt;Rental income at current levels (~AED 130K–170K) covers costs with room to spare&lt;/li&gt;
&lt;li&gt;Net yield after fixed costs is roughly in the 4–6% range at current price levels (AED 2.3M–2.7M)&lt;/li&gt;
&lt;li&gt;Vacancy has asymmetric cost consequences that require explicit modeling&lt;/li&gt;
&lt;li&gt;Market activity has slowed under Iran-conflict conditions, though prices have not yet moved materially&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The "tax-free" framing of UAE investment is accurate as far as it goes — but the cost structure underneath is real and should be modeled explicitly before drawing yield conclusions.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Related: Al Reem Island is now under ADGM jurisdiction (since January 2025). Leases signed after 2024-12-31 are registered via AccessRP under ADGM Real Property Regulations 2024. This has implications for lease enforcement and dispute resolution — covered in a &lt;a href="https://0xkaz.com/writing/al-reem-early-termination/" rel="noopener noreferrer"&gt;separate piece&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>uae</category>
      <category>abudhabi</category>
      <category>investing</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Abu Dhabi, UAE: Early Lease Termination at Al Reem Island During the Iran Conflict</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Thu, 26 Mar 2026 12:10:24 +0000</pubDate>
      <link>https://dev.to/kaz123/abu-dhabi-uae-early-lease-termination-at-al-reem-island-during-the-iran-conflict-3j98</link>
      <guid>https://dev.to/kaz123/abu-dhabi-uae-early-lease-termination-at-al-reem-island-during-the-iran-conflict-3j98</guid>
      <description>&lt;p&gt;&lt;em&gt;Personal experience as a property owner on Al Reem Island. Not legal advice. If you have a specific situation, consult a lawyer.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;In March 2026, not long after the conflict with Iran began, I received an unexpected message from a tenant renting the apartment I own on Al Reem Island in Abu Dhabi. They wanted out early — the security situation felt too uncertain to stay.&lt;/p&gt;

&lt;p&gt;For an owner renting an investment property, early termination means a direct hit to income. But the tenant was living there as their home, and refusing outright without understanding the legal situation first didn't make sense. My first step was to sort out what law actually applied.&lt;/p&gt;




&lt;h2&gt;
  
  
  Al Reem Moved to ADGM — and I Noticed Only When It Mattered
&lt;/h2&gt;

&lt;p&gt;Al Reem Island used to fall under &lt;strong&gt;Abu Dhabi Law No. 20 of 2006&lt;/strong&gt;, with leases registered through Tawtheeq and enforcement handled by ADREC (Abu Dhabi Real Estate Centre).&lt;/p&gt;

&lt;p&gt;When I reviewed the lease I'd signed in August 2025, I remembered noticing that the registration process had changed from what I'd done with a previous property. Instead of Tawtheeq, this one went through a system called &lt;strong&gt;AccessRP&lt;/strong&gt; — run by ADGM, the Abu Dhabi Global Market.&lt;/p&gt;

&lt;p&gt;This turned out to be the result of ADGM expanding its jurisdiction to cover Al Reem Island. The transfer was announced in April 2023 and completed on December 31, 2024. From January 1, 2025, all new leases on Al Reem Island fall under &lt;strong&gt;ADGM Real Property Regulations 2024&lt;/strong&gt;, registered through AccessRP.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;From January 2025&lt;/th&gt;
&lt;th&gt;Before 2025&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Governing law&lt;/td&gt;
&lt;td&gt;ADGM Real Property Regulations 2024&lt;/td&gt;
&lt;td&gt;Abu Dhabi Law No. 20/2006&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Registration system&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;AccessRP&lt;/strong&gt; (ADGM)&lt;/td&gt;
&lt;td&gt;Tawtheeq&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforcement body&lt;/td&gt;
&lt;td&gt;ADGM&lt;/td&gt;
&lt;td&gt;ADREC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dispute resolution&lt;/td&gt;
&lt;td&gt;ADGM Courts&lt;/td&gt;
&lt;td&gt;Rental Dispute Settlement Committee (ADJD)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;One important detail: &lt;strong&gt;leases already registered with Tawtheeq before December 31, 2024 remain valid under the old law.&lt;/strong&gt; There was no forced re-registration. So Al Reem currently has a mix of contracts under two different legal frameworks — the transition period runs through 2025 and 2026 at least.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two Months' Rent: What the Contract Actually Said
&lt;/h2&gt;

&lt;p&gt;Under ADGM Real Property Regulations 2024, unilateral early termination is not freely permitted. The penalty is not a fixed statutory amount — it depends on &lt;strong&gt;what the lease contract says&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;My contract included a clause specifying that early termination requires a penalty equal to &lt;strong&gt;two months' rent&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The tenant initially came back with a counter-offer: could we settle for one month? I didn't respond to that. A while later, the full two-month penalty was transferred into my account.&lt;/p&gt;

&lt;p&gt;There's a detail worth noting: the tenant had actually returned to China for Lunar New Year and never came back. The tenant had a colleague handle the move-out and disposal of belongings from the apartment. This meant there was almost no direct back-and-forth — which, unexpectedly, made the whole thing straightforward. No negotiation theater, just the contract terms enforced cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  When the Standard Payment Method Stopped Working
&lt;/h2&gt;

&lt;p&gt;In the UAE, paying rent by &lt;strong&gt;cheque&lt;/strong&gt; is still standard practice. The penalty payment was initially supposed to come by cheque, but that's where things got complicated.&lt;/p&gt;

&lt;p&gt;My &lt;strong&gt;WIO Bank&lt;/strong&gt; app had a temporary outage affecting its cheque processing function. Given that the Iran conflict had reportedly involved physical attacks on AWS data center infrastructure in the UAE around the same time, I suspected a connection — though I can't confirm it. The cheque function eventually came back, but by then the tenant's cheque had a signature error and couldn't be processed. We switched to a &lt;strong&gt;bank transfer&lt;/strong&gt; instead.&lt;/p&gt;

&lt;p&gt;This kind of friction — where the "standard" method breaks at exactly the wrong moment — is a mundane but real part of managing property remotely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Inquiries Stopped. Prices Haven't Followed — Yet.
&lt;/h2&gt;

&lt;p&gt;Before the Iran conflict started, I was getting roughly &lt;strong&gt;two inquiries per week&lt;/strong&gt; — a mix of rental and sale interest.&lt;/p&gt;

&lt;p&gt;In the month after the conflict began: &lt;strong&gt;one inquiry total&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The drop was immediate and sharp. Demand didn't fade gradually — it stopped.&lt;/p&gt;

&lt;p&gt;What hasn't happened (yet) is a corresponding price collapse. Al Reem Island and the adjacent Al Maryah Island area have held up relatively well compared to other parts of the UAE. There are structural reasons for this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supply is controlled.&lt;/strong&gt; Development on Al Reem Island is concentrated among Aldar, Tamouh, and Reem Investments; Al Maryah is primarily a 60:40 Aldar-Mubadala joint venture. These entities control most of the land, which limits disorderly supply growth. In December 2025, Mubadala and Aldar announced a plan to expand the financial district on Al Maryah Island at a scale exceeding AED 60 billion (~USD 16.3 billion). Long-range development plans like this are not the profile of a market heading for sudden oversupply.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The tenant base is stable.&lt;/strong&gt; Government and semi-government employees on long-term contracts make up a significant share of residents. Short-term rental (Airbnb-style) penetration is lower than Dubai. Speculative foreign capital flows have been more limited. Demand is primarily end-user driven.&lt;/p&gt;

&lt;p&gt;These factors don't make the market immune to a sustained conflict. But they explain why the price response has been slower than the inquiry response.&lt;/p&gt;




&lt;h2&gt;
  
  
  Abu Dhabi's Rental Data Gap Is Finally Closing
&lt;/h2&gt;

&lt;p&gt;A note on the regulatory side: Abu Dhabi's rental market has historically been harder to read than Dubai's because of less transparent data.&lt;/p&gt;

&lt;p&gt;That's changing. ADREC published the city's first residential &lt;strong&gt;Rental Index&lt;/strong&gt; in August 2024. &lt;strong&gt;Madhmoun&lt;/strong&gt; — UAE's first MLS (Multiple Listing Service) — launched to consolidate transaction data and reduce duplicate and fictitious listings.&lt;/p&gt;

&lt;p&gt;Al Reem Island's 2025 rental data reflects this: the area recorded 21% YoY rent growth in Q2 2025 (Quanta transaction data), with property prices up 38% in the same period — the highest appreciation of any Abu Dhabi zone. Abu Dhabi's 5% annual rent increase cap (Law No. 20/2006, Article 16) applies to renewals with the same tenant, not to new contracts. The practical result: landlords can effectively reset to market rates each time a tenant turns over. That's how 5% legal caps coexist with 21% aggregate market growth.&lt;/p&gt;

&lt;p&gt;As ADGM's AccessRP integrates with these data systems, the transparency of Al Reem and Al Maryah should approach Dubai's over time.&lt;/p&gt;




&lt;h2&gt;
  
  
  Finding the Next Tenant While Prices Hold
&lt;/h2&gt;

&lt;p&gt;AccessRP now shows my managed property in a dashboard — a useful practical improvement from the ADGM migration. The next new lease will go through the same ADGM system.&lt;/p&gt;

&lt;p&gt;The market isn't pricing in catastrophe yet. If I can find the next tenant while prices are still holding, that's the realistic goal.&lt;/p&gt;

&lt;p&gt;From an investment standpoint, the Al Reem and Al Maryah zone under ADGM jurisdiction has a specific structural advantage over other Abu Dhabi investment areas — Masdar, Al Raha, Yas, Saadiyat — in three respects: legal framework transparency, English common law tradition, and the ADGM ecosystem. For investors from common law jurisdictions, the shift to a familiar legal framework is a meaningful improvement. Over the long run, that may be reflected in how the market is valued.&lt;/p&gt;




&lt;h2&gt;
  
  
  Legal Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Detail&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Governing law (August 2025 lease)&lt;/td&gt;
&lt;td&gt;ADGM Real Property Regulations 2024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforcement body&lt;/td&gt;
&lt;td&gt;ADGM (from January 2025)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lease registration&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;AccessRP&lt;/strong&gt; (from January 2025; previously Tawtheeq)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dispute resolution&lt;/td&gt;
&lt;td&gt;ADGM Courts (for leases signed from January 2025)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Early termination penalty&lt;/td&gt;
&lt;td&gt;Per contract terms (in this case, 2 months' rent)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Abu Dhabi Law No. 20/2006&lt;/td&gt;
&lt;td&gt;Continues to apply to Tawtheeq-registered leases signed before December 31, 2024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ADGM jurisdiction transfer&lt;/td&gt;
&lt;td&gt;Announced April 2023; completed December 31, 2024&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;em&gt;This article is based on personal experience and is not legal advice. For specific situations, consult a qualified lawyer.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>uae</category>
      <category>realestate</category>
      <category>abudhabi</category>
      <category>property</category>
    </item>
    <item>
      <title>Desert and Rainforest — Why Abu Dhabi and Johor Bahru Became AI Hubs at the Same Time</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Wed, 25 Mar 2026 12:39:48 +0000</pubDate>
      <link>https://dev.to/kaz123/desert-and-rainforest-why-abu-dhabi-and-johor-bahru-became-ai-hubs-at-the-same-time-36hm</link>
      <guid>https://dev.to/kaz123/desert-and-rainforest-why-abu-dhabi-and-johor-bahru-became-ai-hubs-at-the-same-time-36hm</guid>
      <description>&lt;p&gt;&lt;em&gt;Personal analysis. Not investment advice. Data from public sources, Knight Frank, company announcements, and US/UAE/Malaysia government releases. March 2026.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;The two cities have almost nothing in common on the surface. One is a desert oil state, the other an equatorial multi-ethnic nation. Yet both became concentrated destinations for global AI data center investment around the same time — and continue to be.&lt;/p&gt;

&lt;p&gt;Why did the same thing happen in such different places? And beneath the surface similarity, what is fundamentally different?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Shared Logic: Both Absorbed Overflow Demand
&lt;/h2&gt;

&lt;p&gt;JB's growth came from Singapore's moratorium. When Singapore effectively stopped approving new data centers in 2019, demand redirected to JB, one kilometer across the causeway.&lt;/p&gt;

&lt;p&gt;Abu Dhabi's rise has a structurally similar story. Dubai's premium areas face rising land costs and zoning constraints. Abu Dhabi offers purpose-built development zones — KEZAD and Masdar City — where land, power, and infrastructure connections are bundled together by state-backed entities, making large-scale AI campuses easier to develop.&lt;/p&gt;

&lt;p&gt;The investment dynamic was also different from JB in one important way. It was largely the UAE side — Sheikh Tahnoon bin Zayed and G42 — that actively courted US hyperscalers, and the US that responded. The result was Stargate UAE: a joint venture between G42, OpenAI, Oracle, Nvidia, and SoftBank, announced in May 2025 with both the UAE president and Donald Trump present. The planned capacity is 5GW — larger than JB's entire pipeline of 3.4GW.&lt;/p&gt;

&lt;p&gt;Both cities, in other words, were shaped by the same combination of forces: constraints at nearby established hubs, and deliberate investment attraction on their own part.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Key Difference: The Type of Geopolitical Risk
&lt;/h2&gt;

&lt;p&gt;Both cities appear to face "US-China tension" as a risk, but the nature of that tension is completely different.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abu Dhabi chose a side.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;G42 divested from all its Chinese investments in 2023 and 2024, removed an estimated $1.7 to $2 billion worth of Huawei equipment from its data centers, and exited its stake in ByteDance. This was a direct response to US government pressure — effectively a loyalty test. In return, the US approved the export of up to 500,000 advanced NVIDIA processors annually to the UAE.&lt;/p&gt;

&lt;p&gt;The Stargate UAE campus is designed specifically for US hyperscalers, with strict KYC protocols controlling access. This is distinct from the broader UAE market: Alibaba Cloud operates a data center region in Dubai, and Huawei has cloud infrastructure in Saudi Arabia. Stargate UAE is one facility within a region where Chinese operators also have a presence — it is not a China-free zone across the UAE.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Malaysia is trying not to choose.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Malaysian government actively welcomes investment from both sides. Former deputy minister Ong Kian Ming has publicly stated that JB is open to US and Chinese tech companies alike. Prime Minister Anwar maintains a non-aligned posture. The consequence of that openness has been pressure from both directions: the US scrutinized Malaysia as a potential GPU diversion route to China, and when Malaysia cooperated with US oversight requests, China criticized it for taking sides.&lt;/p&gt;

&lt;p&gt;Neither position is obviously right. But the risk profiles are different. Abu Dhabi's risk is concentrated: if its relationship with the US deteriorates for any reason, the entire model breaks. Malaysia's risk is diffuse and ongoing: either side can apply pressure at any time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Physical War Risk
&lt;/h2&gt;

&lt;p&gt;In late February 2026, the US and Israel launched strikes against Iran.&lt;/p&gt;

&lt;p&gt;As of the time of writing, Abu Dhabi's data center infrastructure is exposed to real military risk. The UAE intercepted 165 ballistic missiles, two cruise missiles, and 541 drones over two days of exchanges. Thirty-five drones and five projectiles got through, hitting Jebel Ali Port and buildings in Dubai. An Amazon data center in the UAE reportedly caught fire during the strikes.&lt;/p&gt;

&lt;p&gt;"It is cheaper to attack than to defend." That is the asymmetric reality of the conflict.&lt;/p&gt;

&lt;p&gt;JB has no equivalent physical military risk. The geopolitical squeeze is real, but missiles are not flying toward Johor. For long-term infrastructure investment, that difference is not trivial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Power and Cooling: Desert Versus Rainforest
&lt;/h2&gt;

&lt;p&gt;Abu Dhabi is an oil and gas producer with abundant, stable power. Stargate UAE combines nuclear, solar, and gas in its energy design. Grid reliability is among the highest in the world.&lt;/p&gt;

&lt;p&gt;The challenge is cooling. Servers that generate large amounts of heat in 50°C desert conditions require substantial energy to cool. This pushed Abu Dhabi toward liquid cooling, reclaimed water systems, and seawater cooling years before Malaysia faced the same pressure. The Middle East confronted the "stop using potable water for cooling" problem a decade earlier than JB is confronting it now.&lt;/p&gt;

&lt;p&gt;JB sits on the equator. It is not as hot as Abu Dhabi, but high humidity reduces air cooling efficiency. Power comes from TNB's grid, and whether supply can keep pace with the 3.4GW pipeline remains genuinely uncertain.&lt;/p&gt;

&lt;p&gt;In terms of energy headroom, Abu Dhabi has a clear advantage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Infrastructure Depth: What Is Buried Underground
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://0xkaz.com/writing/abu-dhabi-underground-infrastructure/" rel="noopener noreferrer"&gt;a previous piece about Abu Dhabi&lt;/a&gt;, I wrote about what I found when I looked into the facilities near Al Reem Island that I had walked past without thinking much about.&lt;/p&gt;

&lt;p&gt;The STEP sewage tunnel runs 41 km at depths up to 105 meters, operating entirely on gravity with no intermediate pumping stations. A power outage does not stop it. The Liwa aquifer storage project — the world's largest desalinated water ASR project — holds enough emergency supply to provide the entire city of Abu Dhabi for 90 days. Both were built over decades, largely invisible to residents.&lt;/p&gt;

&lt;p&gt;JB's infrastructure is not yet at that level. Water problems became visible because the underlying systems were too fragile to handle the sudden surge in industrial demand. Bridge DC is building a reclaimed water plant, AirTrunk is deploying liquid cooling, Microsoft is designing zero-water-evaporation facilities. These are real improvements. But they are starting in 2024 and 2025. Abu Dhabi's infrastructure depth took decades to build.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Each City Is Actually Building
&lt;/h2&gt;

&lt;p&gt;This may be the most fundamental difference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abu Dhabi is trying to become an AI-producing country.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Stargate UAE, G42's Falcon (an Arabic-language LLM), Mohamed bin Zayed University of Artificial Intelligence — Abu Dhabi is not just hosting AI infrastructure. It is trying to build the capacity to create AI. The data centers are a means, not an end. The national strategy is to use AI the way oil was used: as the foundation for the next 50 years of economic output.&lt;/p&gt;

&lt;p&gt;The Stargate UAE campus includes a science park for AI innovation. The design integrates research, development, and talent training, not just compute capacity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JB is functioning as a compute location.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JB's role is primarily to serve as a cheaper extension of Singapore. Tenants are multinationals headquartered in Singapore; JB provides the backend at lower cost. Anwar's repeated insistence on economic spillover reflects his recognition that this model, if left unchanged, does not transfer much capability to Malaysia.&lt;/p&gt;

&lt;p&gt;Malaysia has a National AI Strategy (NAIES), and the ambition to use AI for economic development is genuine. But the practical reality is closer to "attract AI infrastructure and extract economic benefit" than "build AI."&lt;/p&gt;

&lt;h2&gt;
  
  
  The Post-Oil Bet
&lt;/h2&gt;

&lt;p&gt;Reading Abu Dhabi's AI investment purely as infrastructure misses the point.&lt;/p&gt;

&lt;p&gt;The Abu Dhabi Economic Vision 2030 was set out in 2006. Its core objective: shift from oil dependence toward a knowledge-intensive economy. By 2025, non-oil sectors already account for over 75 percent of UAE GDP — partly a policy success, partly a reflection of urgency about what comes after oil.&lt;/p&gt;

&lt;p&gt;Seen through this lens, the AI investment is a straightforward move: use oil revenues to buy the next resource. If oil was the defining resource of the 20th century, compute capacity may be the defining resource of the 21st. G42, Mubadala, ADIA, MGX — Abu Dhabi's sovereign capital concentrating in AI infrastructure reflects something more than investment return calculations. It is about securing a strategic resource before the competition locks it down.&lt;/p&gt;

&lt;p&gt;The Stargate UAE announcement framed this explicitly: a facility capable of reaching half the world's population within a 3,200 km radius. India, Pakistan, East Africa, the broader Middle East — all within that range. JB competes on "5ms from Singapore." Abu Dhabi is competing on "AI infrastructure hub for the Global South." The ambition is a different order of magnitude.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Non-Aligned Legacy and Its Limits
&lt;/h2&gt;

&lt;p&gt;The UAE has historically been skilled at not choosing sides. It is a member of the Non-Aligned Movement, joined BRICS in January 2024, maintains security ties with the US, deep economic ties with China, and close trading relationships with India. This multi-alignment strategy — staying useful to all major powers — is how a small country of roughly 10 million people has punched well above its weight diplomatically and economically.&lt;/p&gt;

&lt;p&gt;That equilibrium began to fracture under AI geopolitical pressure in 2023 and 2024.&lt;/p&gt;

&lt;p&gt;G42 removing an estimated $1.7 to $2 billion worth of Huawei equipment and divesting all Chinese investments was a direct response to US pressure — a loyalty test passed. At the same time, the UAE maintained its BRICS membership, continued participating in mBridge (China's cross-border digital currency settlement platform), and kept economic relationships with Chinese firms in other sectors. The architecture being constructed is: technology aligned with the US, financial and economic relationships deliberately diversified.&lt;/p&gt;

&lt;p&gt;Whether this two-layer structure is sustainable depends on how far US-China competition intensifies. As AI infrastructure becomes a more explicit front in that competition, the space for "both sides" shrinks. Abu Dhabi is trying to hold the non-aligned identity while having already made the harder choice at the technology layer. Malaysia's Anwar is attempting the same thing at a different level of commitment.&lt;/p&gt;

&lt;p&gt;Neither will find it easy if the competition continues to escalate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strengths and Risks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Abu Dhabi's strengths:&lt;/strong&gt; State-designed stability. Oil revenues underwrite power and water infrastructure. Clear US alignment secures chip supply. Infrastructure depth provides long-term reliability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Abu Dhabi's risks:&lt;/strong&gt; Direct physical exposure to the Iran conflict. Having chosen a side completely, there is no fallback if the US relationship changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JB's strengths:&lt;/strong&gt; The irreplaceable proximity to Singapore via the causeway. The flexibility to attract both US and Chinese investment. Malaysia's economic growth momentum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JB's risks:&lt;/strong&gt; Continuous US-China pressure from both directions. Power and water infrastructure that is still catching up. The structural risk of remaining a "compute location" without becoming more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same Phenomenon, Different Futures
&lt;/h2&gt;

&lt;p&gt;Abu Dhabi's data center buildup started earlier — Microsoft opened Azure regions there in 2019, and the hyperscale investment wave accelerated through the early 2020s. JB's rapid expansion began around 2023, following the ChatGPT moment. Both pipelines now extend well into the 2030s. On the surface it looks like the same story. Underneath, the design logic is fundamentally different.&lt;/p&gt;

&lt;p&gt;Ten to twenty years from now, the divergence will likely be clearer. Abu Dhabi will have become a genuine AI-producing hub in deep partnership with the US — or the long war in the Middle East will have disrupted that ambition. JB will have absorbed Singapore's overflow demand steadily and pragmatically — or newer competitors like Batam will have eroded its advantage.&lt;/p&gt;

&lt;p&gt;The reasons to watch both are specific: Abu Dhabi for the depth of its state-backed infrastructure and its firm US alignment; JB for the proximity to Singapore that no other city can replicate. Those are entirely different reasons — which is precisely the point. Having once lived in Abu Dhabi, now on MM2H in Malaysia with property on Al Reem, I have had an unusually direct view of both.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Related terms: Stargate UAE, G42, MGX (Abu Dhabi AI investment vehicle), STEP (Abu Dhabi deep sewer tunnel), ASR (Aquifer Storage and Recovery), JS-SEZ, NAIES (Malaysia's National AI Strategy). Related: &lt;a href="https://0xkaz.com/writing/uae-solar-ai-infrastructure/" rel="noopener noreferrer"&gt;UAE Solar Is Cheaper Than Qatar's Gas&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>infrastructure</category>
      <category>uae</category>
      <category>malaysia</category>
      <category>ai</category>
    </item>
    <item>
      <title>What I Found Underground in Abu Dhabi While Reading About Iran's Attacks on Gulf Desalination Plants</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Wed, 25 Mar 2026 11:07:17 +0000</pubDate>
      <link>https://dev.to/kaz123/what-i-found-underground-in-abu-dhabi-while-reading-about-irans-attacks-on-gulf-desalination-plants-1f6l</link>
      <guid>https://dev.to/kaz123/what-i-found-underground-in-abu-dhabi-while-reading-about-irans-attacks-on-gulf-desalination-plants-1f6l</guid>
      <description>&lt;p&gt;&lt;em&gt;Personal analysis. Not investment advice. Geopolitical data from Wikipedia, Al Jazeera, Xinhua. Infrastructure data from DEWA, ADSSC, WaterWorld, MEED. March 2026.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On February 28, 2026, the US and Israel launched strikes against Iran.&lt;/p&gt;

&lt;p&gt;From the start, the conflict went in an unexpected direction. Targets were not just military sites — desalination plants started getting hit. On March 7, a plant on Iran's Qeshm Island was attacked (Iran blamed the US; the US and Israel denied it). The next day, an Iranian drone struck a desalination facility in Bahrain. In Fujairah, UAE, the port and oil storage facilities took direct hits, triggering fires and suspending oil operations.&lt;/p&gt;

&lt;p&gt;One researcher put it plainly: "Oil built the Persian Gulf. Desalinated water keeps it alive." That infrastructure is now part of the conflict.&lt;/p&gt;

&lt;h2&gt;
  
  
  The "Dubai loses water in one strike" claim
&lt;/h2&gt;

&lt;p&gt;Social media has been circulating a story that Dubai is one attack away from a water crisis, because everything depends on Jebel Ali.&lt;/p&gt;

&lt;p&gt;The concern is not completely unfounded. Jebel Ali holds a Guinness World Record as the world's largest single-site desalination facility, producing 490 million imperial gallons of water per day. It covers most of Dubai's water and electricity supply.&lt;/p&gt;

&lt;p&gt;But "one strike and it's over" is an exaggeration.&lt;/p&gt;

&lt;p&gt;Jebel Ali is actually made up of 43 MSF (Multi-Stage Flash) distillation units plus 2 reverse osmosis plants, spread across stations D, E, G, K, L, and M. A single explosion cannot take all of them down simultaneously. Dubai also has additional smaller plants, and there is a wider water transmission grid across the UAE that allows inter-emirate supply in emergencies.&lt;/p&gt;

&lt;p&gt;On top of that, DEWA had been working toward a 90-day emergency underground water reserve at Jebel Ali, targeting a storage capacity of 6,000 million imperial gallons when complete.&lt;/p&gt;

&lt;p&gt;There is real risk here. But it is not a single point of failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I actually wanted to write about: Abu Dhabi's infrastructure
&lt;/h2&gt;

&lt;p&gt;While going through all of this, I ended up down a rabbit hole about Abu Dhabi's water and sanitation systems — and found some things I had not expected.&lt;/p&gt;

&lt;p&gt;I invest in property on Al Reem Island, so I have walked past various utility buildings and facilities there without thinking much about them. I had no idea what was actually inside them, or what was happening underneath.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why does Abu Dhabi flood when it rains?
&lt;/h2&gt;

&lt;p&gt;Abu Dhabi gets rain maybe once or twice a year. When it does, roads stay flooded for half a day. For one of the wealthiest cities in the world, the drainage seems oddly inadequate.&lt;/p&gt;

&lt;p&gt;The reasoning is straightforward: cost versus frequency.&lt;/p&gt;

&lt;p&gt;Building a billion-dollar stormwater drainage network for rain that comes two days a year makes no economic sense. In a desert environment, drainage pipes also face constant problems — sand clogging and salt corrosion make maintenance expensive. So roads temporarily flooding is accepted as a minor inconvenience.&lt;/p&gt;

&lt;p&gt;What is not accepted as an inconvenience is the water supply failing. That is treated as an existential problem, and the spending reflects it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Liwa underground water reserve
&lt;/h2&gt;

&lt;p&gt;About 160 km southwest of Abu Dhabi city, beneath the Liwa sand dunes, sits the world's largest desalinated water Aquifer Storage and Recovery (ASR) project.&lt;/p&gt;

&lt;p&gt;The concept: pump surplus desalinated water into the underground sand aquifer during periods of high production, then recover it when needed. Abu Dhabi started feasibility studies in 2001, ran pilots from 2003 to 2009, built the full facility from 2009 to 2016, and has been running large-scale injection since 2015. Total investment was around $350 million.&lt;/p&gt;

&lt;p&gt;Storage capacity is approximately 26 million cubic meters, with recovery efficiency of 85–95%. The target: supply the entire city of Abu Dhabi for 90 days from this reserve alone.&lt;/p&gt;

&lt;p&gt;This is not something you see mentioned in real estate brochures. But it is sitting under the desert.&lt;/p&gt;

&lt;h2&gt;
  
  
  A sewer tunnel that goes 105 meters underground
&lt;/h2&gt;

&lt;p&gt;This is the part I found most surprising.&lt;/p&gt;

&lt;p&gt;Abu Dhabi has a deep gravity sewer system called STEP — the Strategic Tunnel Enhancement Programme. Total cost: approximately $1.9 billion. The main tunnel runs 41 km from Abu Dhabi island through the mainland to a treatment facility at Al Wathba. An additional 43 km of link sewers feed into it, making the total network around 84 km.&lt;/p&gt;

&lt;p&gt;The depth is what stands out.&lt;/p&gt;

&lt;p&gt;The tunnel starts at around 27 meters below ground on Abu Dhabi island. As it reaches the mainland it descends to 80 meters. At the deepest point — the Al Wathba pumping station — it reaches &lt;strong&gt;105 meters underground&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The reason for going that deep is straightforward engineering: the system runs on gravity alone for nearly its entire length. To move wastewater by gravity over 35+ km without intermediate pumping stations, you need a continuous downward slope, which means digging deeper as you go. This design eliminated 35 existing pump stations across the network, removing a significant number of failure points.&lt;/p&gt;

&lt;p&gt;The treated output does not go to waste. Wastewater collected through STEP is 100% recycled and used for irrigation — the parks, grass, and trees you see around Abu Dhabi are kept green with reclaimed water that traveled 105 meters underground before being cleaned and distributed.&lt;/p&gt;

&lt;p&gt;One detail worth noting: in some areas of Al Reem Island, vacuum trucks still collect sewage the old way. The deep tunnel infrastructure and the vacuum truck coexist. That gap is a reasonable picture of where the city's infrastructure priorities sit.&lt;/p&gt;

&lt;h2&gt;
  
  
  The cooling risk that doesn't get talked about
&lt;/h2&gt;

&lt;p&gt;Al Reem Island has its own water supply and district cooling infrastructure — including a 57,000-refrigerant-ton cooling plant serving the Shams development.&lt;/p&gt;

&lt;p&gt;District cooling is the dominant air conditioning model across the UAE. Instead of individual outdoor units on each building, a central plant produces chilled water and distributes it through underground pipes to connected buildings. It is more energy-efficient and makes sense at urban scale.&lt;/p&gt;

&lt;p&gt;For Al Reem, this means the island has a degree of self-sufficiency. Even if cut off from the mainland, it can continue producing cooling, at least while the island's plants are running.&lt;/p&gt;

&lt;p&gt;But here is the structural weak point.&lt;/p&gt;

&lt;p&gt;Water can be piped over long distances. Chilled water cannot. Heat loss over long pipe runs makes it impractical to supply district cooling from far away. If the cooling plant on the island were damaged or shut down, there is no quick way to route cooling from the Abu Dhabi mainland.&lt;/p&gt;

&lt;p&gt;In a city where summer temperatures exceed 50°C, losing air conditioning is not just uncomfortable. It makes a building uninhabitable within hours. By that measure, the real infrastructure vulnerability in the UAE is not water — it's cooling supply continuity.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually determines a city's asset value
&lt;/h2&gt;

&lt;p&gt;In a world where physical infrastructure attacks are no longer hypothetical, I think what determines the long-term value of urban real estate is what you cannot see from the street.&lt;/p&gt;

&lt;p&gt;Not the towers. Not the mall. Not the view.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A sewer tunnel buried 105 meters underground, built to last 100 years&lt;/li&gt;
&lt;li&gt;90 days of emergency drinking water stored in an aquifer 160 km away&lt;/li&gt;
&lt;li&gt;Nine geographically distributed desalination plants connected by 3,500 km of pipelines&lt;/li&gt;
&lt;li&gt;An island-level cooling system that can run independently if needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are the things a national government spends billions on over decades, quietly, without much fanfare.&lt;/p&gt;

&lt;p&gt;"How impressive does it look from above" is a reasonable thing to evaluate. But "how robust is what's below" is probably more relevant when you're thinking about what happens if things get difficult.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Related: &lt;a href="https://0xkaz.com/writing/uae-solar-ai-infrastructure/" rel="noopener noreferrer"&gt;UAE Solar Is Cheaper Than Qatar's Gas. Notes on Gulf AI Infrastructure Power.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>infrastructure</category>
      <category>discuss</category>
      <category>watermanagement</category>
      <category>uae</category>
    </item>
    <item>
      <title>UAE Solar Is Cheaper Than Qatar's Gas. Notes on Gulf AI Infrastructure Power.</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Tue, 24 Mar 2026 21:06:37 +0000</pubDate>
      <link>https://dev.to/kaz123/uae-solar-is-cheaper-than-qatars-gas-notes-on-gulf-ai-infrastructure-power-4dik</link>
      <guid>https://dev.to/kaz123/uae-solar-is-cheaper-than-qatars-gas-notes-on-gulf-ai-infrastructure-power-4dik</guid>
      <description>&lt;p&gt;Iran's strikes on Gulf gas infrastructure over the past months have accelerated a conversation that was already happening in GCC energy circles. The Ras Laffan disruption — Qatar's LNG processing complex, the largest in the world, being disrupted — made a structural question suddenly urgent: what happens to Gulf AI infrastructure plans when the power supply isn't physically secure?&lt;/p&gt;

&lt;p&gt;Here's what makes that question interesting for infrastructure builders: Iran's strikes didn't cause this, but they made it visible. UAE solar auction prices fell below Qatar's subsidized gas electricity rate years ago — not recently. The two facts are unrelated in cause but connected in what they mean.&lt;/p&gt;

&lt;h2&gt;
  
  
  The price inversion that already happened (years ago)
&lt;/h2&gt;

&lt;p&gt;Starting around 2019 and accelerating through 2025, UAE wholesale solar got cheaper than Qatar's subsidized gas grid. This didn't happen because of the current conflict. It happened because of solar cost economics.&lt;/p&gt;

&lt;p&gt;UAE solar auction prices are now $0.014–0.024/kWh. Qatar's business electricity rate (KAHRAMAA, subsidized gas) is $0.036/kWh. That's a 33–60% gap — in the wrong direction from what most people assume about GCC energy.&lt;/p&gt;

&lt;p&gt;Dubai's MBR Solar Park Phase 3 cleared at $0.0299/kWh in 2017. Phase 5 hit $0.01653/kWh. Phase 6 (DEWA, 1.8 GW, Masdar as developer) cleared at &lt;strong&gt;$0.01622/kWh&lt;/strong&gt; and went operational in Q4 2024. Abu Dhabi's Al Khazna IPP (EWEC, 1.5 GW, Engie + Masdar) was awarded in 2025 at &lt;strong&gt;$0.01459/kWh&lt;/strong&gt; — the lowest utility-scale solar price in the region. Even the 2019 Noor Abu Dhabi price ($0.0242/kWh) was 33% cheaper than Qatar's current gas rate.&lt;/p&gt;

&lt;p&gt;Price trajectory: $0.0242 (2019) → $0.01653 → $0.01622 → $0.01459 (2025). About 40% down over six years. Driven by Chinese panel manufacturing scale, better project financing, and Abu Dhabi's high solar irradiance (~2,200 kWh/kWp/year).&lt;/p&gt;

&lt;p&gt;The inversion happened well before any geopolitical disruption. Iran's attacks didn't create it. They made it matter to a different audience.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the Ras Laffan disruption changes
&lt;/h2&gt;

&lt;p&gt;Qatar's Ras Laffan industrial city is not just an LNG processing hub. It is Qatar's power generation supply chain. The country runs on gas. Gas processing happens at Ras Laffan. The grid follows from there.&lt;/p&gt;

&lt;p&gt;Iran's strikes surfaced a concentration risk that Gulf infrastructure planners always knew was there but treated as low-probability. The deterrence assumption — that attacking Qatar's LNG would invite overwhelming response — is now being tested.&lt;/p&gt;

&lt;p&gt;For AI infrastructure planning, this matters in a specific way. Long-duration GPU infrastructure has a 5–10 year capital horizon. Decisions made in 2026 pick power supply arrangements running into the 2030s. "Low-probability geopolitical risk" looks different once it's been realized once.&lt;/p&gt;

&lt;p&gt;The failure mode difference: a Ras Laffan attack disrupts Qatar's entire power generation supply chain — one geographic concentration. An attack on UAE solar farms is damaging but not systemically crippling — panels are distributed across large areas, replaceable from a global supply chain, and Barakah nuclear plants are hardened, dispersed facilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The intermittency problem nobody lets you skip
&lt;/h2&gt;

&lt;p&gt;Cheap solar at $0.014/kWh is not cheap AI power. Not yet. Data centers need power 24/7. Solar delivers 8–12 hours a day, peaking around noon and dropping hard after 4pm. A GPU cluster doing model training doesn't care that the sun is down.&lt;/p&gt;

&lt;p&gt;UAE retail electricity ($0.082–0.095/kWh for business customers) is a blended rate: cheap solar when the sun is up, gas peakers at night. Large data centers negotiate direct PPA terms at scale — but even a direct solar PPA leaves the nighttime problem unsolved. The project that changes this is now funded and under construction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Masdar's round-the-clock project
&lt;/h2&gt;

&lt;p&gt;In January 2025, Masdar and EWEC announced a &lt;strong&gt;5.2 GW solar PV + 19 GWh battery storage&lt;/strong&gt; complex designed to deliver &lt;strong&gt;1 GW of firm, 24/7 power&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Numbers: $6B capital cost. EPC: PowerChina + Larsen &amp;amp; Toubro. Panels: Jinko Solar + JA Solar. Batteries: CATL. Groundbreaking: October 2025. Target operational: &lt;strong&gt;2027&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The math: 5.2 GW at Abu Dhabi capacity factors generates ~11,000 GWh/year. That's ~1.25 GW average across 8,760 hours. The 19 GWh of storage bridges the overnight gap (roughly 4–6 hours at 1 GW discharge rate). EWEC and Masdar have been explicit: the target use case is AI data center baseload power.&lt;/p&gt;

&lt;p&gt;At $6/W of firm capacity, the upfront cost is higher than combined-cycle gas ($1–1.5/W). But marginal fuel cost is zero and supply chain risk is manufacturing, not commodity or geopolitical.&lt;/p&gt;

&lt;h2&gt;
  
  
  What UAE data centers actually run on today
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Khazna AUH6 (G42, Masdar City):&lt;/strong&gt; 31.8 MW AI-ready facility, operational. Has a dedicated 7 MWp direct solar PPA through Emerge (Masdar + EDF joint venture).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stargate UAE (1 GW cluster, Abu Dhabi)&lt;/strong&gt; power stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nuclear:&lt;/strong&gt; Barakah (4 × ~1.4 GW APR-1400, online 2020–2024) — the UAE is the only Arab country with operating nuclear power. Always-on low-carbon baseload.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Solar/storage:&lt;/strong&gt; Masdar 5.2 GW RTC project (2027 target).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gas bridge:&lt;/strong&gt; TAQA + EWEC 1 GW OCGT, $980M, operational December 2025. Dispatchable backup until solar+storage comes online.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  UAE vs Qatar: the trajectory
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Qatar (today)&lt;/th&gt;
&lt;th&gt;UAE (2024)&lt;/th&gt;
&lt;th&gt;UAE (2027)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cheapest power&lt;/td&gt;
&lt;td&gt;Gas $0.036/kWh&lt;/td&gt;
&lt;td&gt;Solar PPA $0.014/kWh&lt;/td&gt;
&lt;td&gt;Solar+storage $0.014/kWh firm&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24/7 firm renewable&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (Masdar RTC)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nuclear baseload&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes (Barakah)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gas dependency&lt;/td&gt;
&lt;td&gt;Very high&lt;/td&gt;
&lt;td&gt;Declining&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LNG concentration risk&lt;/td&gt;
&lt;td&gt;Ras Laffan (actualized 2026)&lt;/td&gt;
&lt;td&gt;Distributed&lt;/td&gt;
&lt;td&gt;More distributed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What I'm taking from this
&lt;/h2&gt;

&lt;p&gt;The energy economics argument against UAE for long-duration AI infrastructure — "it's hot, solar is intermittent, gas backup is expensive" — is getting structurally dismantled. The sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Solar auction prices below Qatar's subsidized gas rate. Already done.&lt;/li&gt;
&lt;li&gt;Barakah nuclear: always-on low-carbon baseload no other GCC state has. Operational now.&lt;/li&gt;
&lt;li&gt;Masdar 5.2 GW RTC: 1 GW firm solar power with no gas dependency, if it delivers in 2027.&lt;/li&gt;
&lt;li&gt;OCGT gas bridge covers the gap until then.&lt;/li&gt;
&lt;li&gt;Ras Laffan disruption: priced gas-grid concentration risk in a way it wasn't priced before.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What the conflict didn't change: GPU export controls (still the main GCC AI friction), data sovereignty requirements, talent density.&lt;/p&gt;

&lt;p&gt;Variables worth tracking: Masdar RTC construction progress through 2026–2027; whether EWEC offers direct PPA terms below Stargate-scale (10–100 MW); GPU export control trajectory for UAE under the current US administration.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Personal analysis, not investment advice. Data from public sources: Masdar newsroom, DEWA, EWEC, PV Tech, Data Center Dynamics, KAHRAMAA. March 2026.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>cloudcomputing</category>
      <category>infrastructure</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Building a Website from My Phone with Claude Code + Telegram</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Tue, 24 Mar 2026 19:09:03 +0000</pubDate>
      <link>https://dev.to/kaz123/building-a-website-from-my-phone-with-claude-code-telegram-12n1</link>
      <guid>https://dev.to/kaz123/building-a-website-from-my-phone-with-claude-code-telegram-12n1</guid>
      <description>&lt;p&gt;I built &lt;a href="https://0xkaz.com" rel="noopener noreferrer"&gt;0xkaz.com&lt;/a&gt; almost entirely from my phone. My machine runs at home in KL. I was in a café in KL, or traveling in Baguio or Abu Dhabi — opening Telegram, typing what I wanted, and watching the site change.&lt;/p&gt;

&lt;p&gt;The mechanism is Claude Code's Telegram channel plugin. You run Claude Code on a machine at home, install the plugin, point it at your repo, and from that point your Telegram chat becomes a terminal. Claude can read files, edit code, run shell commands, and deploy — all triggered by a message. Location stops mattering.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the loop actually works
&lt;/h2&gt;

&lt;p&gt;The setup is straightforward. Install the plugin, configure your bot token, and set &lt;code&gt;TELEGRAM_STATE_DIR&lt;/code&gt; in &lt;code&gt;.claude/settings.json&lt;/code&gt; to a directory inside the repo rather than &lt;code&gt;~/.claude/&lt;/code&gt;. That one setting matters: it keeps the bot state version-controlled alongside the project instead of floating loose in your home directory.&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;"env"&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="nl"&gt;"TELEGRAM_STATE_DIR"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/repo/.claude/channels/telegram"&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;From that point, the interaction is just messaging. I'd send "add a dark mode toggle to the nav" and Claude would read the relevant components, make the edits, and reply with what it changed. I'd send "deploy" and it would run the build and push to Cloudflare Pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills make it one-command
&lt;/h2&gt;

&lt;p&gt;The real productivity gain came from creating skills — small &lt;code&gt;SKILL.md&lt;/code&gt; files that define slash commands for common operations. I have &lt;code&gt;/commit&lt;/code&gt;, &lt;code&gt;/push&lt;/code&gt;, &lt;code&gt;/deploy&lt;/code&gt;, and &lt;code&gt;/feedback&lt;/code&gt;. Each one tells Claude exactly what to run and what to report back.&lt;/p&gt;

&lt;p&gt;Sending &lt;code&gt;/deploy&lt;/code&gt; from Telegram and getting back a live URL two minutes later, without touching a laptop, doesn't get old.&lt;/p&gt;

&lt;h2&gt;
  
  
  The feedback form got built this way too
&lt;/h2&gt;

&lt;p&gt;The most satisfying part: the feedback form at the bottom of each article on this site was designed, implemented, and wired up entirely through Telegram. I described what I wanted — Cloudflare Worker receiving submissions, D1 for storage, Resend for email confirmation, Telegram notification back to me when someone submits — and Claude built the whole stack.&lt;/p&gt;

&lt;p&gt;That took a few back-and-forth messages across an afternoon. Async. I'd send something, close Telegram, come back an hour later, read the result, send the next instruction.&lt;/p&gt;

&lt;h2&gt;
  
  
  What works well
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Full async development.&lt;/strong&gt; This is the actual unlock. You don't have to sit there watching a terminal. Send the message, go do something else, come back to results. For side projects where you have 20 minutes here and there, this changes the math completely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No context switching.&lt;/strong&gt; One thread. Claude maintains context across the session — it remembers that we're using Tailwind v4 syntax, that the deployment target is Cloudflare Pages, that the Worker is in &lt;code&gt;/worker&lt;/code&gt; and the site is in &lt;code&gt;/site&lt;/code&gt;. I don't re-explain the project structure every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ship-it decisions are frictionless.&lt;/strong&gt; "Commit and push this." One message. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to watch
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No visual feedback.&lt;/strong&gt; You can't see the rendered site in Telegram. For layout and CSS work this is a real limitation — Claude can make confident but wrong decisions about spacing and responsive behavior without a browser to check. Complex UI changes need a laptop eventually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Session limits.&lt;/strong&gt; Long tasks can hit context limits or time out. For anything complex, ask Claude to commit frequently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credentials need care.&lt;/strong&gt; Sensitive tokens belong in &lt;code&gt;.claude/settings.local.json&lt;/code&gt; (gitignored), not in the tracked &lt;code&gt;settings.json&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How close to fully automated?
&lt;/h2&gt;

&lt;p&gt;Close, but not there. The loop handles execution well — once you know what you want, Claude can build it. The part that still requires a human is direction. What feature to add next, whether a design choice feels right, whether the copy says the right thing.&lt;/p&gt;

&lt;p&gt;The risk isn't that Claude does things wrong — it's that it does things confidently in a direction you didn't quite intend. Catching that requires enough technical understanding to read a diff and recognize when something is off. You don't need to write all the code, but you need to know what good looks like.&lt;/p&gt;

&lt;p&gt;Think of it as a skilled contractor who needs clear briefs. Technical fluency makes your briefs better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it worth it?
&lt;/h2&gt;

&lt;p&gt;For a side project running on Cloudflare's stack, yes, clearly. The infrastructure overhead is already low and the Telegram interface removes the laptop requirement for most operations.&lt;/p&gt;

&lt;p&gt;What surprised me is how much of software development is actually amenable to this. Reading logs, querying databases, deploying, committing, adding features described in plain language — that's most of what I do on a side project. The parts that don't work (visual QA, complex debugging with browser devtools) are genuinely the minority.&lt;/p&gt;

&lt;p&gt;The site you're reading this on was built this way.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Notes from building &lt;a href="https://0xkaz.com" rel="noopener noreferrer"&gt;0xkaz.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Crawling GCC Government Documents: What Blocked Me</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Mon, 23 Mar 2026 13:54:41 +0000</pubDate>
      <link>https://dev.to/kaz123/crawling-gcc-government-documents-what-blocked-me-2bj1</link>
      <guid>https://dev.to/kaz123/crawling-gcc-government-documents-what-blocked-me-2bj1</guid>
      <description>&lt;p&gt;Building GCC LexAI meant ingesting AI regulation documents from UAE and Saudi Arabia government websites. The tech stack worked fine. The websites did not always cooperate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saudi .gov.sa blocks non-Saudi traffic entirely
&lt;/h2&gt;

&lt;p&gt;This took me a while to accept as the actual explanation.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cst.gov.sa&lt;/code&gt;, &lt;code&gt;cma.gov.sa&lt;/code&gt;, &lt;code&gt;sdaia.gov.sa&lt;/code&gt;, and their subdomains return connection timeouts. Not 403s, not redirects — timeouts. I tried from Japan, Malaysia, and the US. Same result every time. The problem isn't the origin country; it's that Saudi government sites appear to block all non-Saudi IP ranges at the network level.&lt;/p&gt;

&lt;p&gt;Changing your crawler's location doesn't help. Proxies in GCC countries are the theoretical fix, but the practical one is to not depend on primary government URLs at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What worked:&lt;/strong&gt; Some agencies publish via CDN subdomains (&lt;code&gt;cdn.nca.gov.sa&lt;/code&gt;), which resolve from outside Saudi Arabia. For agencies without CDN mirrors, I used documents hosted by OECD, law firms, and academic institutions — the same PDFs, just not from the primary &lt;code&gt;.gov.sa&lt;/code&gt; domain.&lt;/p&gt;

&lt;h2&gt;
  
  
  sca.gov.ae returns HTML where you expect a PDF
&lt;/h2&gt;

&lt;p&gt;The Securities and Commodities Authority's PDF URLs respond with &lt;code&gt;Content-Type: text/html&lt;/code&gt; and serve a webpage. Not a redirect, not an error — a 200 response with HTML content at what looks like a PDF path.&lt;/p&gt;

&lt;p&gt;Detection fix: check the first four bytes of the response body for &lt;code&gt;%PDF&lt;/code&gt;. If the content-type says PDF but the bytes don't, discard it and find another source. VARA (the virtual assets regulator) hosts its rulebooks on a CDN with clean, stable URLs — that became the fallback for SCA content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Don't rely on official URLs as your primary source for government documents.&lt;/strong&gt; &lt;code&gt;.gov&lt;/code&gt; domains optimize for human browsers, not automated access. CDN mirrors and secondary hosts are often more reliable for programmatic use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treat PDF availability as data you need to verify.&lt;/strong&gt; A URL that returns 200 isn't necessarily a PDF. A PDF URL that works today may return HTML tomorrow. Build verification into the ingestion pipeline, not as an afterthought.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Geo-blocking is a real constraint in the GCC.&lt;/strong&gt; UAE government sites were accessible. Saudi ones were not. Design your data sources with this asymmetry in mind if you're building anything cross-GCC.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Notes from building &lt;a href="https://gcc-lexai.0xkaz.com" rel="noopener noreferrer"&gt;GCC LexAI&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>python</category>
      <category>crawler</category>
      <category>ai</category>
    </item>
    <item>
      <title>Introducing kotoba v0.0.1: Natural Language Web Testing with 6x Speed Improvement</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Thu, 19 Jun 2025 16:14:55 +0000</pubDate>
      <link>https://dev.to/kaz123/introducing-kotoba-v001-natural-language-web-testing-with-6x-speed-improvement-i9j</link>
      <guid>https://dev.to/kaz123/introducing-kotoba-v001-natural-language-web-testing-with-6x-speed-improvement-i9j</guid>
      <description>&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.amazonaws.com%2Fuploads%2Farticles%2Fi5xtfkrqcbakhbw5awhu.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fi5xtfkrqcbakhbw5awhu.png" alt="kotoba - Natural Language Web Testing" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;On June 20th, 2025, we released kotoba v0.0.1, a natural language web testing tool with groundbreaking performance improvements. This article details our technical approach achieving 6x speed improvement through a staged fallback strategy and 203 pattern matching rules in our assertion system implementation.&lt;/p&gt;

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

&lt;p&gt;Kotoba is a Python tool that enables web testing through natural language instructions. By combining Playwright with LLMs, it automates browser interactions using intuitive commands like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Click the "Login" button
Enter "test@example.com" in the email field
Enter "password123" in the password field
Click the "Submit" button
Verify that "Login successful" message is displayed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Challenge: LLM Processing Bottleneck
&lt;/h2&gt;

&lt;p&gt;The biggest challenge in natural language testing tools is processing speed. When all instructions are processed through LLM:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Average processing time&lt;/strong&gt;: 1.1-1.6 seconds per instruction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cause&lt;/strong&gt;: LLM inference processing required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Impact&lt;/strong&gt;: Massive execution time for large test suites&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve this challenge, we adopted a strategy of pre-defining frequent patterns to minimize LLM dependency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Solution: Staged Fallback Strategy
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Architecture Design
&lt;/h3&gt;

&lt;p&gt;We implemented a two-stage processing flow in kotoba:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Natural Language Instruction
    ↓
【Stage 1】Assertion Pattern Matching (&amp;lt; 1ms)
    ↓ (match found)
✅ Execute Assertion
    ↓ (no match)
【Stage 2】LLM-based General Action Processing (100-1000ms)
    ↓
🎯 Execute Browser Action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. 25 Assertion Types
&lt;/h3&gt;

&lt;p&gt;We implemented comprehensive assertion types for thorough test validation:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Text-related assertions
&lt;/span&gt;    &lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;TEXT_NOT_EXISTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_not_exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;TEXT_EQUALS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_equals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;TEXT_CONTAINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text_contains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Element-related assertions
&lt;/span&gt;    &lt;span class="n"&gt;ELEMENT_EXISTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;element_exists&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;ELEMENT_VISIBLE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;element_visible&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;ELEMENT_ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;element_enabled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# URL/Title assertions
&lt;/span&gt;    &lt;span class="n"&gt;URL_CONTAINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;url_contains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;TITLE_CONTAINS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;title_contains&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Form assertions
&lt;/span&gt;    &lt;span class="n"&gt;INPUT_VALUE_EQUALS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_value_equals&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;CHECKBOX_CHECKED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;checkbox_checked&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="c1"&gt;# ... 13 more types
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. 203 Pattern Matching Rules
&lt;/h3&gt;

&lt;p&gt;To handle natural language diversity, we implemented 203 patterns across multiple categories:&lt;/p&gt;

&lt;h4&gt;
  
  
  Basic Japanese Patterns
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Text existence verification
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[「&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(.+?)[」&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?が(?:表示されて|出て|見えて)?(?:いる|いること|いることを)(?:確認|チェック|検証)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

&lt;span class="c1"&gt;# Polite form support
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[「&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(.+?)[」&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?が(?:表示されて|出て|見えて)?(?:いる|いること|いることを)(?:確認|チェック|検証)(?:します|してください|お願いします)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&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;h4&gt;
  
  
  Colloquial and Question Forms
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Kansai dialect
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[「&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(.+?)[」&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(?:が|って)(?:出てる|見える)(?:で|やん|やんか|わ|な)(?:？|\?)?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

&lt;span class="c1"&gt;# Question forms
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[「&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(.+?)[」&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(?:は|が)(?:表示されて|見えて)(?:いますか|いるでしょうか|いるか)(?:？|\?)?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&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;h4&gt;
  
  
  English and Chinese Patterns
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# English patterns
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?:verify|check|confirm|assert)(?:\s+that)?\s+[\"&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;](.+?)[\"&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;]\s+(?:is|exists?|appears?|is\s+(?:visible|displayed|present))&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

&lt;span class="c1"&gt;# Chinese patterns
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;(?:验证|检查|确认|断言)[\"&lt;/span&gt;&lt;span class="sh"&gt;'""&lt;/span&gt;&lt;span class="s"&gt;](.+?)[&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="sh"&gt;'""&lt;/span&gt;&lt;span class="s"&gt;](?:存在|显示|出现)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&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;h4&gt;
  
  
  Domain-Specific Patterns
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# IT/Web industry
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[「&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(.+?)[」&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(?:が|の)(?:レンダリング|描画|出力)(?:が|は)(?:正常|適切|問題なし)(?:か|かどうか)(?:確認|検証|チェック)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

&lt;span class="c1"&gt;# Form elements
&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[「&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(.+?)[」&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="s"&gt;]?(?:ボタン|button|Button|按钮|按鈕)(?:が|は)(?:表示|存在|クリック可能|押せる|有効)(?:になって|で|に)(?:いる|いること)(?:を|について)?(?:確認|検証|チェック)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
 &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ELEMENT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;button&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;
  
  
  Technical Implementation Details
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Pattern Matching Engine
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AssertionPatternMatcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&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;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assertion_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;param_type&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PATTERNS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;instruction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Flexible quote handling
&lt;/span&gt;                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;groups&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="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;「」&lt;/span&gt;&lt;span class="sh"&gt;""''&lt;/span&gt;&lt;span class="se"&gt;\'\'&lt;/span&gt;&lt;span class="sh"&gt;""'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;assertion_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;expected&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;selector&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;  &lt;span class="c1"&gt;# Fall back to LLM
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Assertion Execution Engine
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AssertionExecutor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Assertion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AssertionResult&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;start_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;AssertionType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TEXT_EXISTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="c1"&gt;# Multiple selector strategy for robustness
&lt;/span&gt;                &lt;span class="n"&gt;selectors&lt;/span&gt; &lt;span class="o"&gt;=&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;text=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expected&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text=*&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;*&lt;/span&gt;&lt;span class="sh"&gt;"&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;:has-text(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;)&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;selector&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;selectors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="n"&gt;elements&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query_selector_all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AssertionResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...)&lt;/span&gt;

        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;AssertionResult&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;error_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Improvement Results
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Dramatic Processing Time Reduction
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Pattern Count&lt;/th&gt;
&lt;th&gt;LLM Usage&lt;/th&gt;
&lt;th&gt;Avg Processing Time&lt;/th&gt;
&lt;th&gt;Speed Improvement&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;54 (initial)&lt;/td&gt;
&lt;td&gt;30%&lt;/td&gt;
&lt;td&gt;300ms&lt;/td&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;130 (interim)&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;td&gt;100ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;3x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;203 (current)&lt;/td&gt;
&lt;td&gt;5%&lt;/td&gt;
&lt;td&gt;50ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;6x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500 (target)&lt;/td&gt;
&lt;td&gt;1%&lt;/td&gt;
&lt;td&gt;10ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;30x faster&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Test Success Rate Enhancement
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Success Rate&lt;/strong&gt;: 100% (6/6 test cases)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Handling&lt;/strong&gt;: Robust fallback mechanisms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internationalization&lt;/strong&gt;: Japanese, English, Chinese support&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Real-World Usage Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  YAML Test Cases
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Assertion&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Function&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Test"&lt;/span&gt;
&lt;span class="na"&gt;base_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://example.com"&lt;/span&gt;

&lt;span class="na"&gt;test_cases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Basic&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Text&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Verification"&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Verify&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Example&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Domain'&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;is&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;displayed"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Check&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;that&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;URL&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;contains&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;example.com"&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Colloquial&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Expression&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Test"&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Domainって表示されてる？"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;instruction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Can&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;see&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Example&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Domain?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Execution Results
&lt;/h3&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;"assertion_result"&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="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"text_exists"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"passed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"expected"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Text 'Example Domain' exists 1 or more times"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"actual"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"execution_time_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.17&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;h2&gt;
  
  
  Pattern Categories (23 categories, 203 patterns)
&lt;/h2&gt;

&lt;p&gt;Our comprehensive pattern coverage includes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Form Element Patterns&lt;/strong&gt; - Buttons, links, input fields, select boxes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Status &amp;amp; State Patterns&lt;/strong&gt; - Loading, errors, success, warnings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media Patterns&lt;/strong&gt; - Images, videos, icons&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Table &amp;amp; List Patterns&lt;/strong&gt; - Table data, list items, counts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Modal &amp;amp; Popup Patterns&lt;/strong&gt; - Modals, dialogs, alerts, notifications&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Navigation Patterns&lt;/strong&gt; - Menus, tabs, navigation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Accessibility Patterns&lt;/strong&gt; - ARIA, focus, screen readers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Responsive &amp;amp; Device Patterns&lt;/strong&gt; - Mobile, responsive design&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Patterns&lt;/strong&gt; - Speed, response time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Patterns&lt;/strong&gt; - HTTPS, SSL, secure connections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Special Character Patterns&lt;/strong&gt; - Symbols, required marks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Date &amp;amp; Time Patterns&lt;/strong&gt; - Dates, times, current time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Price &amp;amp; Amount Patterns&lt;/strong&gt; - Prices, totals, currency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Count &amp;amp; Number Patterns&lt;/strong&gt; - Counts, remaining items&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Login &amp;amp; Auth Patterns&lt;/strong&gt; - Login status, user info&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Download &amp;amp; Upload Patterns&lt;/strong&gt; - File operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Progress Patterns&lt;/strong&gt; - Progress, progress bars&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Message &amp;amp; Text Patterns&lt;/strong&gt; - Info, hints&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation Patterns&lt;/strong&gt; - Validation errors, validity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sort &amp;amp; Filter Patterns&lt;/strong&gt; - Ascending, descending, order&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Search &amp;amp; Filter Patterns&lt;/strong&gt; - Filters, search results&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pagination Patterns&lt;/strong&gt; - Page numbers, next/previous&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language &amp;amp; i18n Patterns&lt;/strong&gt; - Language switching, localization&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Future Roadmap
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Phase 2: Machine Learning-Assisted Pattern Generation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automatic pattern extraction from log data&lt;/li&gt;
&lt;li&gt;Dynamic optimization based on usage frequency&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Phase 3: Ultimate Speed Optimization
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Implementation of 500+ patterns&lt;/li&gt;
&lt;li&gt;Achieving sub-millisecond processing times&lt;/li&gt;
&lt;li&gt;Community-driven pattern database construction&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Our assertion system implementation in kotoba achieved:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;6x Speed Improvement&lt;/strong&gt;: 300ms → 50ms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;203 Patterns&lt;/strong&gt;: Comprehensive natural language support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;100% Test Success Rate&lt;/strong&gt;: Robust error handling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multilingual Support&lt;/strong&gt;: Japanese, English, Chinese&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This work demonstrates new possibilities in the convergence of natural language processing and web test automation. By combining pattern matching with LLM, we've successfully balanced ease of use with high performance.&lt;/p&gt;

&lt;p&gt;kotoba v0.0.1 was released on June 20th, 2025, and is available as open source. We continue our pursuit of becoming the world's highest-performance natural language testing tool through ongoing improvements.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/0xkaz/kotoba" rel="noopener noreferrer"&gt;kotoba&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Release Date&lt;/strong&gt;: June 20th, 2025 (v0.0.1)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Tech Stack&lt;/strong&gt;: Python, Playwright, LLM, Regex&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Tags&lt;/strong&gt;: #testing #automation #nlp&lt;/p&gt;

</description>
      <category>testing</category>
      <category>automation</category>
      <category>python</category>
      <category>nlp</category>
    </item>
    <item>
      <title>🚀 LLMCommit: AI-Powered Git Commit Message Generator in 2.5 Seconds</title>
      <dc:creator>kaz</dc:creator>
      <pubDate>Tue, 17 Jun 2025 09:54:26 +0000</pubDate>
      <link>https://dev.to/kaz123/llmcommit-ai-powered-git-commit-message-generator-in-25-seconds-58op</link>
      <guid>https://dev.to/kaz123/llmcommit-ai-powered-git-commit-message-generator-in-25-seconds-58op</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Stop wasting time writing commit messages. &lt;code&gt;llmcommit -a -p&lt;/code&gt; generates meaningful messages and pushes your code in 2.5 seconds using rule-based AI + caching.&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.amazonaws.com%2Fuploads%2Farticles%2Fa3q7ntglrtpz1pwg4hdd.png" 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.amazonaws.com%2Fuploads%2Farticles%2Fa3q7ntglrtpz1pwg4hdd.png" alt="Image description" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem Every Developer Faces
&lt;/h2&gt;

&lt;p&gt;Let's be honest - how much time do you spend writing commit messages?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# We've all been there...&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"update"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"changes"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"wip"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The hidden cost:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3-5 minutes per commit thinking of proper messages&lt;/li&gt;
&lt;li&gt;Breaking your coding flow to context-switch&lt;/li&gt;
&lt;li&gt;Inconsistent message quality across team members&lt;/li&gt;
&lt;li&gt;Non-native English speakers struggling with proper phrasing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Meet LLMCommit
&lt;/h2&gt;

&lt;p&gt;LLMCommit is a blazing-fast CLI tool that generates meaningful git commit messages using AI, then handles the entire git workflow for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⚡ Speed Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;3-5 minutes&lt;/td&gt;
&lt;td&gt;"update" / "fix stuff"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LLMCommit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;2.5 seconds&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;"Update user authentication logic"&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  🎯 One Command, Complete Workflow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Before: 3 commands + thinking time&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"..."&lt;/span&gt; &lt;span class="c"&gt;# 🤔 what should I write?&lt;/span&gt;
git push

&lt;span class="c"&gt;# After: 1 command&lt;/span&gt;
llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Technical Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Rule-Based Engine (Default - 2.5s)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of always hitting LLMs, LLMCommit uses intelligent pattern matching:&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="n"&gt;PATTERNS&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;config&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;.json&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;settings&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;env&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;docs&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;readme&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;.md&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;changelog&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;test&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;test&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;spec&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;__test__&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;fix&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;fix&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;bug&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;error&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;feat&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;add&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;new&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;create&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Analysis Process:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;File Pattern Detection&lt;/strong&gt;: Identifies file types and purposes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Diff Analysis&lt;/strong&gt;: Examines added/removed lines&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context Generation&lt;/strong&gt;: Creates appropriate message based on patterns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Quality Assurance&lt;/strong&gt;: Ensures messages follow conventional commit style&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Smart Caching System&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.cache/llmcommit/
├── outputs/           # Generated messages (24h TTL)
├── models/            # Model metadata 
└── cache_metadata.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Cache Strategy:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Key&lt;/strong&gt;: &lt;code&gt;SHA256(model:diff[:500])[:16]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hit Time&lt;/strong&gt;: &amp;lt;0.1 seconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistence&lt;/strong&gt;: 24 hours for outputs, permanent for models&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Progressive Enhancement&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When rule-based isn't enough, fall back to LLM:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ultra-fast rule-based (default)&lt;/span&gt;
llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;                    &lt;span class="c"&gt;# 2.5s&lt;/span&gt;

&lt;span class="c"&gt;# Lightweight LLM (SmolLM-135M)  &lt;/span&gt;
llmcommit &lt;span class="nt"&gt;--preset&lt;/span&gt; ultra-light &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;  &lt;span class="c"&gt;# 3-5s&lt;/span&gt;

&lt;span class="c"&gt;# High-performance LLM (TinyLlama-1.1B)&lt;/span&gt;
llmcommit &lt;span class="nt"&gt;--preset&lt;/span&gt; light &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;         &lt;span class="c"&gt;# 5-8s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Installation &amp;amp; Usage
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Quick Start
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;llmcommit

&lt;span class="c"&gt;# Use (creates .llmcommit.json config automatically)&lt;/span&gt;
llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advanced Usage
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Dry run (see message without committing)&lt;/span&gt;
llmcommit &lt;span class="nt"&gt;--dry-run&lt;/span&gt;

&lt;span class="c"&gt;# Skip git hooks for maximum speed&lt;/span&gt;
llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;--no-verify&lt;/span&gt;

&lt;span class="c"&gt;# Cache management&lt;/span&gt;
llmcommit-cache stats
llmcommit-cache clear &lt;span class="nt"&gt;--days&lt;/span&gt; 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before LLMCommit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
a1b2c3d update
e4f5g6h fix
i7j8k9l changes
m0n1o2p wip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  After LLMCommit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git log &lt;span class="nt"&gt;--oneline&lt;/span&gt;
a1b2c3d Update user authentication middleware
e4f5g6h Fix memory leak &lt;span class="k"&gt;in &lt;/span&gt;cache manager  
i7j8k9l Add unit tests &lt;span class="k"&gt;for &lt;/span&gt;payment service
m0n1o2p Update API documentation &lt;span class="k"&gt;for &lt;/span&gt;v2.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Performance Benchmarks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Speed Tests (MacBook Pro M1)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Cold Start&lt;/th&gt;
&lt;th&gt;Warm Start&lt;/th&gt;
&lt;th&gt;Cache Hit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rule-based&lt;/td&gt;
&lt;td&gt;2.5s&lt;/td&gt;
&lt;td&gt;2.5s&lt;/td&gt;
&lt;td&gt;0.1s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SmolLM-135M&lt;/td&gt;
&lt;td&gt;45s&lt;/td&gt;
&lt;td&gt;4s&lt;/td&gt;
&lt;td&gt;0.1s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TinyLlama-1.1B&lt;/td&gt;
&lt;td&gt;60s&lt;/td&gt;
&lt;td&gt;7s&lt;/td&gt;
&lt;td&gt;0.1s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Memory Usage
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;RAM Usage&lt;/th&gt;
&lt;th&gt;Disk Cache&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Rule-based&lt;/td&gt;
&lt;td&gt;~10MB&lt;/td&gt;
&lt;td&gt;~1MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SmolLM-135M&lt;/td&gt;
&lt;td&gt;~400MB&lt;/td&gt;
&lt;td&gt;~270MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TinyLlama-1.1B&lt;/td&gt;
&lt;td&gt;~2.2GB&lt;/td&gt;
&lt;td&gt;~2.2GB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Advanced Configuration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Custom Presets
&lt;/h3&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;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HuggingFaceTB/SmolLM-135M"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"max_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"temperature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"prompt_template"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Generate commit: {diff}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"use_fast"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cache_dir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"~/.cache/llmcommit"&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;h3&gt;
  
  
  Team Integration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .llmcommit.json (commit to repo)&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="s2"&gt;"use_fast"&lt;/span&gt;: &lt;span class="nb"&gt;true&lt;/span&gt;,
  &lt;span class="s2"&gt;"prompt_template"&lt;/span&gt;: &lt;span class="s2"&gt;"[JIRA-{ticket}] {diff}"&lt;/span&gt;,
  &lt;span class="s2"&gt;"team_convention"&lt;/span&gt;: &lt;span class="s2"&gt;"conventional-commits"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Docker Support
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build optimized image&lt;/span&gt;
make build

&lt;span class="c"&gt;# Run with persistent cache&lt;/span&gt;
docker run &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/app &lt;span class="nt"&gt;-v&lt;/span&gt; llmcommit_cache:/cache llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Persistent Volumes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;huggingface_cache&lt;/code&gt;: Model downloads (reused across containers)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;llmcommit_cache&lt;/code&gt;: Generated message cache&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Production Tips
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;CI/CD Integration&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/auto-commit.yml&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Auto-commit changes&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;llmcommit -a -p --no-verify&lt;/span&gt;
  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. &lt;strong&gt;Git Hooks&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# .git/hooks/prepare-commit-msg&lt;/span&gt;
&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-z&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
  &lt;/span&gt;llmcommit &lt;span class="nt"&gt;--dry-run&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. &lt;strong&gt;Monorepo Support&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Different configs per service&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;services/auth &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;services/api &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nt"&gt;--config&lt;/span&gt; .llmcommit-api.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Comparison with Alternatives
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Speed&lt;/th&gt;
&lt;th&gt;Quality&lt;/th&gt;
&lt;th&gt;Offline&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;LLMCommit&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2.5s&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI API&lt;/td&gt;
&lt;td&gt;3-5s&lt;/td&gt;
&lt;td&gt;Very High&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;$0.01/commit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Copilot&lt;/td&gt;
&lt;td&gt;5-10s&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;$10/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manual&lt;/td&gt;
&lt;td&gt;180s+&lt;/td&gt;
&lt;td&gt;Variable&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;Developer time&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Q: How accurate are the generated messages?&lt;/strong&gt;&lt;br&gt;
A: Rule-based mode achieves ~85% satisfaction rate. LLM modes reach ~95%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Does it work offline?&lt;/strong&gt;&lt;br&gt;
A: Yes! After initial model download, everything runs locally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: What about security?&lt;/strong&gt;&lt;br&gt;
A: No code leaves your machine. All processing is local.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Q: Can I customize the message format?&lt;/strong&gt;&lt;br&gt;
A: Absolutely. Supports conventional commits, custom templates, and team conventions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔄 &lt;strong&gt;Smart Branching&lt;/strong&gt;: Different message styles per branch type&lt;/li&gt;
&lt;li&gt;🤖 &lt;strong&gt;Custom Models&lt;/strong&gt;: Fine-tuned models for specific codebases
&lt;/li&gt;
&lt;li&gt;📊 &lt;strong&gt;Analytics&lt;/strong&gt;: Commit pattern analysis and suggestions&lt;/li&gt;
&lt;li&gt;🔗 &lt;strong&gt;IDE Integration&lt;/strong&gt;: VS Code, JetBrains plugins&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Contributing
&lt;/h2&gt;

&lt;p&gt;LLMCommit is open source! We welcome contributions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/0xkaz/llmcommit
&lt;span class="nb"&gt;cd &lt;/span&gt;llmcommit
make &lt;span class="nb"&gt;local
&lt;/span&gt;make &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Areas we need help:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Additional language model support&lt;/li&gt;
&lt;li&gt;IDE plugin development
&lt;/li&gt;
&lt;li&gt;Documentation improvements&lt;/li&gt;
&lt;li&gt;Performance optimizations&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Stop wasting time on commit messages. LLMCommit gives you back 15-30 minutes per day to focus on what matters: writing great code.&lt;/p&gt;

&lt;p&gt;Try it today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;llmcommit
llmcommit &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your future self (and your git log) will thank you! 🚀&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🐙 &lt;a href="https://github.com/0xkaz/llmcommit" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📚 &lt;a href="https://github.com/0xkaz/llmcommit#readme" rel="noopener noreferrer"&gt;Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐛 &lt;a href="https://github.com/0xkaz/llmcommit/issues" rel="noopener noreferrer"&gt;Issues &amp;amp; Feature Requests&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>git</category>
      <category>productivity</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
