<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="https://thakicloud.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://thakicloud.github.io/" rel="alternate" type="text/html" /><updated>2026-06-24T12:24:36+09:00</updated><id>https://thakicloud.github.io/feed.xml</id><title type="html">Thaki Cloud Tech Blog | ThakiCloud | 다키클라우드 기술 블로그</title><subtitle>Thaki Cloud (ThakiCloud, 다키클라우드, thaki cloud, THAKI CLOUD, ثاكي كلاود)는 AI/ML Engineering, LLMOps, DevOps 분야의 최신 기술과 실무 경험을 공유하는 전문 기술 블로그입니다. 머신러닝 모델 운영, 쿠버네티스, 클라우드 인프라, AI 엔지니어링 커리어, 인공지능 기술 블로그, 다키클라우드 개발 팀의 깊이 있는 인사이트를 제공합니다. مدونة تقنية متخصصة في هندسة الذكاء الاصطناعي والحوسبة السحابية.</subtitle><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><entry xml:lang="ar"><title type="html">محاكيات أندرويد داخل حاويات - بناء مزرعة أجهزة قابلة للتكرار على Kubernetes باستخدام docker-android</title><link href="https://thakicloud.github.io/ar/dev/docker-android-k8s-emulator/" rel="alternate" type="text/html" title="محاكيات أندرويد داخل حاويات - بناء مزرعة أجهزة قابلة للتكرار على Kubernetes باستخدام docker-android" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/ar/dev/docker-android-k8s-emulator</id><content type="html" xml:base="https://thakicloud.github.io/ar/dev/docker-android-k8s-emulator/"><![CDATA[<pre><code class="language-mermaid">flowchart LR
    subgraph NODE["عقدة K8s مع KVM / Pod"]
      EMU["محاكي Android (QEMU + KVM، اختياري CUDA)"]
      KVM["/dev/kvm"]
    end
    KVM --&gt;|passthrough| EMU
    EMU --&gt; SVC["خدمة ADB"]
    SVC --&gt; CI["مزرعة CI"]
    SVC --&gt; SCRCPY["تحكم scrcpy عن بُعد"]
</code></pre>
<h2 id="نظرة-عامة">نظرة عامة</h2>

<p>اختبار تطبيق موبايل يستلزم أجهزة أندرويد. إدارة أسطول من الأجهزة الحقيقية عبء صيانة مُضنٍ، وتثبيت محاكٍ ثقيل على كل جهاز مطوّر يُفضي إلى اختلاف البيئات وضعف قابلية التكرار. تتضاعف هذه المشكلة حين تُريد إدراج اختبارات أندرويد في خط CI، إذ يحتاج كل عقدة بناء إلى إعداد محاكٍ متسق.</p>

<p>يحل <code class="language-plaintext highlighter-rouge">docker-android</code> (إصدار HQarroum) هذه المشكلة بالحاويات. يُغلّف محاكي أندرويد بتهيئة بسيطة، ويُشغّله بلا واجهة رسومية، ويُتيح ADB والتحكم بالشاشة عبر الشبكة. حاوية واحدة توفر بيئة أندرويد نظيفة ومتسقة في ثوانٍ، مما يجعلها مناسبة تماماً لـ CI/CD والاختبارات الآلية.</p>

<p>يتحقق هذا المقال من بنية docker-android ومتطلباته الفعلية وفق التوثيق، ثم يستعرض كيف تتعامل منصة Kubernetes مثل ThakiCloud مع هذا النوع من أحمال عمل الأجهزة. محاكاة أندرويد ليست في صميم منصتنا للذكاء الاصطناعي، لكن السؤال حول عزل الحاويات ذات الامتيازات التي تحتاج KVM passthrough وتسريع GPU يتقاطع مباشرة مع قدرات بنيتنا التحتية.</p>

<hr />

<h2 id="ما-هو-docker-android">ما هو docker-android</h2>

<p>يجمع docker-android الخاص بـ HQarroum بين محاكي أندرويد ودعم KVM و JRE 11 في صورة مدمجة مبنية على Alpine (الإصدار الحالي 1.1.0). النية التصميمية واضحة: كشف محاكي أندرويد كامل يمكن التحكم به عن بُعد بأقل بصمة برمجية ممكنة. تحتوي الصورة على المحاكي نفسه، وخادم ADB للوصول الخارجي، وQEMU مع libvirt.</p>

<p>الخصائص الرئيسية:</p>

<ul>
  <li><strong>بصمة بسيطة</strong>: مبنية على Alpine لتحسين الحجم. البناء بدون SDK أو محاكٍ ينتج صورة أصغر بكثير.</li>
  <li><strong>قابلية التخصيص</strong>: إصدار أندرويد ونوع الجهاز ونوع الصورة كلها قابلة للاختيار.</li>
  <li><strong>توجيه المنافذ مدمج</strong>: يُكشف المحاكي و ADB عبر واجهة شبكة الحاوية.</li>
  <li><strong>بلا واجهة رسومية</strong>: لا تحتاج إلى GUI، مما يجعلها مناسبة لمزارع CI. يمكن الوصول إلى الشاشة عن بُعد عبر <a href="https://github.com/Genymobile/scrcpy">scrcpy</a>.</li>
  <li><strong>قابلية التكرار</strong>: تُعاد صورة المحاكي إلى حالتها الأصلية عند كل إعادة تشغيل، فكل تشغيل يبدأ من حالة متطابقة.</li>
</ul>

<p>يُوضح الرسم البياني أعلاه نشراً افتراضياً لهذه الحاوية على ThakiCloud Kubernetes. يعمل المحاكي في pod على عقدة مُفعَّل فيها KVM مع تمرير <code class="language-plaintext highlighter-rouge">/dev/kvm</code>، ويُستخدم المتغير cuda حين يُحتاج تسريع GPU. يُكشف ADB كـ Service ليصل إليه مزرعة CI و scrcpy.</p>

<hr />

<h2 id="التثبيت-والتكامل">التثبيت والتكامل</h2>

<p>يجمع البناء الافتراضي Android SDK وأدوات المنصة والمحاكي في الصورة. تشغيل كل شيء باستخدام docker-compose:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># المحاكي الأساسي</span>
docker compose up android-emulator

<span class="c"># تسريع GPU</span>
docker compose up android-emulator-cuda

<span class="c"># تسريع GPU + Google Play Store</span>
docker compose up android-emulator-cuda-store
</code></pre></div></div>

<p>يمكن البناء مباشرة باستخدام Docker:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">-t</span> android-emulator <span class="nb">.</span>
</code></pre></div></div>

<p>بعد بناء الصورة، شغّل الحاوية مع تثبيت محرك KVM. استخدام صورة Play Store يستلزم مشاركة المحاكي والعميل لنفس <code class="language-plaintext highlighter-rouge">adbkey</code>؛ أنشئه بـ <code class="language-plaintext highlighter-rouge">adb keygen adbkey</code> وضعه في مجلد <code class="language-plaintext highlighter-rouge">./keys</code>.</p>

<p>يتباين حجم الصورة تبايناً كبيراً حسب متغير البناء. جدول المقارنة من توثيق المستودع:</p>

<table>
  <thead>
    <tr>
      <th>متغير البناء</th>
      <th>غير مضغوط</th>
      <th>مضغوط</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>API 33 + المحاكي</td>
      <td>5.84 GB</td>
      <td>1.97 GB</td>
    </tr>
    <tr>
      <td>API 32 + المحاكي</td>
      <td>5.89 GB</td>
      <td>1.93 GB</td>
    </tr>
    <tr>
      <td>API 28 + المحاكي</td>
      <td>4.29 GB</td>
      <td>1.46 GB</td>
    </tr>
    <tr>
      <td>بدون SDK أو محاكٍ</td>
      <td>414 MB</td>
      <td>138 MB</td>
    </tr>
  </tbody>
</table>

<p>الصور التي تتضمن المحاكي تتجاوز 1.5 GB حتى بعد الضغط. عند التوزيع على عقد كثيرة، يجب مراعاة عرض نطاق السجل وسعة قرص العقد.</p>

<hr />

<h2 id="التحقق-من-السلوك-الفعلي">التحقق من السلوك الفعلي</h2>

<p>لم يشمل هذا المقال التحقق من إقلاع الحاوية فعلياً. تسجيل أمين: فشل التحقق هنا (لا يوجد Docker daemon على المضيف، وmacOS لا يوفر <code class="language-plaintext highlighter-rouge">/dev/kvm</code>). يتطلب docker-android تسريع KVM للأجهزة، لذا التشغيل الفعلي ممكن فقط على مضيف Linux أو عقدة KVM تدعم المحاكاة الافتراضية المتداخلة.</p>

<p>ما أمكن التحقق منه استُقي مباشرة من توثيق المستودع. جدول مقارنة أحجام الصور أعلاه يعكس أرقاماً مُصرَّحاً بها في التوثيق؛ متغيرات البناء وأسماء خدمات compose ومتطلبات تثبيت KVM كلها مستندة إلى التوثيق. أرقام كوقت الإقلاع أو معدل معالجة الاختبارات التي لم نقسها لم نُدرجها. عند النشر الفعلي، بعد توفير عقد KVM، الإجراء الصحيح هو قياس وقت إقلاع الحاوية وزمن استجابة ADB والحد الأقصى لعدد المحاكيات المتزامنة مباشرة.</p>

<hr />

<h2 id="الآثار-على-منصة-thakicloud-k8s-aiml-saas">الآثار على منصة ThakiCloud K8s AI/ML SaaS</h2>

<p>docker-android ليس أداة ذكاء اصطناعي في حد ذاتها. لكن المتطلبات التشغيلية التي يكشف عنها تتقاطع بدقة مع ما تُتقنه ThakiCloud.</p>

<p>أولاً، <strong>عزل أحمال عمل مرور الأجهزة</strong>. المحاكي حاوية ذات امتيازات في جوهرها تتطلب <code class="language-plaintext highlighter-rouge">/dev/kvm</code>. تشغيل هذا النوع من أحمال العمل بأمان في بيئة Kubernetes متعددة المستأجرين يستلزم اختيار العقد بعناية والمكوّنات الإضافية للأجهزة وسياقات الأمان. تُجهّز ThakiCloud بالفعل وحدات GPU عبر مكوّنات الأجهزة الإضافية وKueue؛ يمكن التعامل مع KVM passthrough بالنمط ذاته.</p>

<p>ثانياً، <strong>مزارع الاختبار القابلة للتكرار</strong>. تغليف المحاكيات عديمة الواجهة الرسومية كحاويات يتيح توسيع البيئات النظيفة أفقياً عبر عدد العقد المطلوب. تشغيل اختبارات Appium UI متوازية كثيرة من خط CI/CD حالة استخدام نموذجية لجدولة وظائف Kubernetes.</p>

<p>ثالثاً، ونظرة إلى الأمد البعيد، يمتد هذا بشكل طبيعي نحو <strong>التحقق من أداء الذكاء الاصطناعي على الجهاز</strong>. التحقق من سلوك النماذج الخفيفة أو العوامل العاملة على أجهزة الموبايل على نطاق واسع يتطلب مزرعة أجهزة تنشئ بيئات أندرويد معزولة كثيرة وتُشغّل اختبارات الانحدار آلياً. هذا ليس اهتماماً محورياً لمنصتنا اليوم، لكن مع نضج قدرات تنظيم GPU والأجهزة متعددة المستأجرين لدينا، تغدو مزرعة QA للذكاء الاصطناعي على الموبايل من هذا النوع شيئاً يمكن تقديمه على البنية التحتية ذاتها.</p>

<p>باختصار، docker-android ليس منتجاً نبنيه، لكنه دراسة حالة جيدة في ترويض أحمال عمل الحاويات الثقيلة التي تجمع بين الامتياز ومرور الأجهزة وتسريع GPU على Kubernetes. هذه صورة ملموسة لقدرات تنظيم Kubernetes للأغراض العامة التي تُؤكد عليها ThakiCloud.</p>

<hr />

<h2 id="القيود-والاعتراضات">القيود والاعتراضات</h2>

<ul>
  <li><strong>اعتماديات ثقيلة</strong>: تسريع KVM للأجهزة غير قابل للتفاوض. في البيئات التي لا تدعم المحاكاة الافتراضية المتداخلة، يتدهور الأداء بشكل حاد أو لا يُقلع المحاكي أصلاً. اختيار عقدة السحابة يصبح قيداً صارماً.</li>
  <li><strong>تضخم الصورة</strong>: الصور التي تتضمن المحاكي تبلغ عدة GB حتى بعد الضغط. التوزيع عبر عقد كثيرة يُراكم تكاليف السجل والقرص.</li>
  <li><strong>البُعد عن صلة الذكاء الاصطناعي</strong>: بصراحة، هذه الأداة بعيدة عن أحمال عمل التدريب والاستدلال التي تمثل صميم منصتنا. للمؤسسات التي ليس لديها طلب اختبار موبايل، القيمة المباشرة محدودة. قيمة هذا المقال ليست في “المحاكي بحد ذاته” بل في “أنماط تشغيل حاويات مرور الأجهزة”.</li>
  <li><strong>أمن الحاويات ذات الامتيازات</strong>: الوصول إلى <code class="language-plaintext highlighter-rouge">/dev/kvm</code> وإعدادات الامتياز تُعقّد حدود أمان المستأجرين المتعددين. الحفاظ على عزل المستأجرين يستلزم مجمّعات عقد مخصصة وسياسات صارمة.</li>
</ul>

<p>docker-android أداة قوية لأتمتة اختبارات الموبايل، ومرجع مفيد لكيفية التعامل مع أحمال عمل الأجهزة على Kubernetes. حتى قبل اللحظة التي نحتاجها فيها مباشرة، أنماط التشغيل تستحق الإلمام بها مسبقاً.</p>

<hr />

<h2 id="المصادر">المصادر</h2>

<ul>
  <li>docker-android (HQarroum): <a href="https://github.com/HQarroum/docker-android">https://github.com/HQarroum/docker-android</a></li>
  <li>صورة Docker Hub: <code class="language-plaintext highlighter-rouge">halimqarroum/docker-android</code></li>
  <li>scrcpy (التحكم بالشاشة عن بُعد): <a href="https://github.com/Genymobile/scrcpy">https://github.com/Genymobile/scrcpy</a></li>
  <li>التغريدة الأصلية: <a href="https://x.com/hjguyhan/status/2069427245295493446">https://x.com/hjguyhan/status/2069427245295493446</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="dev" /><category term="docker" /><category term="android" /><category term="kubernetes" /><category term="kvm" /><category term="ci-cd" /><summary type="html"><![CDATA[يُغلّف docker-android محاكي أندرويد في حاوية واحدة ويُشغّله بلا واجهة رسومية. نتحقق من أحجام الصور ومتطلبات KVM وفق التوثيق الرسمي، ونستعرض كيفية تشغيل أحمال عمل مرور الأجهزة على منصة ThakiCloud Kubernetes.]]></summary></entry><entry xml:lang="ar"><title type="html">توجيه Claude Code إلى نماذجك الخاصة — بنية برمجة فعّالة التكلفة باستخدام claude-code-router</title><link href="https://thakicloud.github.io/ar/llmops/claude-code-router-onprem-routing/" rel="alternate" type="text/html" title="توجيه Claude Code إلى نماذجك الخاصة — بنية برمجة فعّالة التكلفة باستخدام claude-code-router" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/ar/llmops/claude-code-router-onprem-routing</id><content type="html" xml:base="https://thakicloud.github.io/ar/llmops/claude-code-router-onprem-routing/"><![CDATA[<pre><code class="language-mermaid">flowchart LR
    CC["Claude Code"] --&gt; CCR["وسيط claude-code-router"]
    CCR --&gt;|default / background| GLM["Ollama Cloud · glm-5.2"]
    CCR --&gt;|think / longContext| MM["MiniMax-M2.7 (نقطة Anthropic)"]
    CCR -.-&gt;|وسم الوكيل الفرعي للبرمجة| KIMI["Ollama Cloud · kimi-k2.7-code"]
    CCR -.-&gt;|خيار محلي| VLLM["vLLM داخلي (GLM-air)"]
    AUDIT["حلقة قياس التكلفة اليومية"] --&gt;|تتحقق مقابل Sonnet| CCR
</code></pre>

<h2 id="نظرة-عامة">نظرة عامة</h2>

<p>‏Claude Code أداة برمجة وكيلية تعمل في الطرفية. افتراضياً تُرسِل الطلبات إلى واجهة Anthropic، لكن ليست كل الطلبات بالوزن نفسه. فالتلخيص الخلفي، والإكمال القصير، وتحليل السياق الطويل، والاستدلال العميق لإعادة الهيكلة تتطلب جميعها مستويات نماذج مختلفة. إذا أرسلت كل شيء إلى أغلى نموذج تتراكم التكلفة، وإذا أرسلت كل شيء إلى أرخصها تنهار الجودة.</p>

<p>يحل <code class="language-plaintext highlighter-rouge">claude-code-router</code> (واختصاراً CCR) هذه المشكلة عبر طبقة توجيه. يقف كوسيط بين Claude Code وخلفيات النماذج ويفرّع الحركة حسب نوع الطلب. هذا المقال ليس مجرد جولة مفاهيمية، بل سجل لاستدعاء ثلاثة نماذج خارجية للتحقق من سلوكها، وإصلاح المشكلات المكتشفة في الطريق (مفتاح API ميت، وتسرّب وسوم التفكير)، وأخيراً إرفاق حلقة تقيس باستمرار ما إذا كان التوجيه أرخص فعلاً من Sonnet.</p>

<p>المبدأ الحاكم، نذكره مقدّماً: <strong>كل نموذج يُوجَّه عبر CCR لا قيمة له إلا إذا كان أكثر كفاءة في التكلفة من Claude Sonnet.</strong> وإلا فإنك تخفض الجودة بينما يستمر صرف المال. لذلك لا نؤكّد، بل نقيس.</p>

<hr />

<h2 id="ما-هو-claude-code-router">ما هو claude-code-router</h2>

<p>‏CCR وسيط يتلقى طلبات بصيغة Anthropic، ويحوّلها إلى صيغة متوافقة مع OpenAI (أو غيرها)، ثم يمرّرها إلى المزوّد المُعَدّ. لا يعدّل عميل Claude Code. شغّل جلسة بـ <code class="language-plaintext highlighter-rouge">ccr code</code> فتُوجَّه حركة تلك الجلسة عبر الوسيط على <code class="language-plaintext highlighter-rouge">localhost:3456</code>.</p>

<p>أبرز الميزات:</p>

<ul>
  <li><strong>التوجيه حسب نوع الطلب</strong>: <code class="language-plaintext highlighter-rouge">default</code> و<code class="language-plaintext highlighter-rouge">background</code> و<code class="language-plaintext highlighter-rouge">think</code> و<code class="language-plaintext highlighter-rouge">longContext</code> و<code class="language-plaintext highlighter-rouge">webSearch</code>، لكلٍّ نموذج مختلف.</li>
  <li><strong>تعدّد المزوّدين</strong>: أي نقطة متوافقة مع OpenAI يمكن تسجيلها. نستخدم هنا Ollama Cloud وMiniMax.</li>
  <li><strong>المحوّلات (transformers)</strong>: يمتص المحوّل خصوصيات كل مزوّد. ومحوّل التمرير <code class="language-plaintext highlighter-rouge">Anthropic</code> لنقاط Anthropic الأصلية هو الأداة المحورية في هذا المقال.</li>
  <li><strong>التبديل الديناميكي</strong>: غيّر النموذج أثناء الجلسة بـ <code class="language-plaintext highlighter-rouge">/model provider,model</code>.</li>
</ul>

<p>إصدار CCR المُتحقَّق منه هو <code class="language-plaintext highlighter-rouge">1.0.62</code>. يقع الإعداد في <code class="language-plaintext highlighter-rouge">~/.claude-code-router/config.json</code>، ومحوره مصفوفة <code class="language-plaintext highlighter-rouge">Providers</code> وكائن <code class="language-plaintext highlighter-rouge">Router</code>.</p>

<hr />

<h2 id="ماذا-يُوجَّه--مثبَّت-على-ثلاثة-نماذج">ماذا يُوجَّه — مثبَّت على ثلاثة نماذج</h2>

<p>مجموعة النماذج ثلاثة بالضبط. فزيادة النماذج تعقّد جدول التوجيه وترفع كلفة التحقق، لذا ضيّقناها عمداً.</p>

<table>
  <thead>
    <tr>
      <th>الدور</th>
      <th>النموذج</th>
      <th>المزوّد</th>
      <th>ملاحظة</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>الأساسي (default/background)</td>
      <td><code class="language-plaintext highlighter-rouge">glm-5.2</code></td>
      <td>Ollama Cloud</td>
      <td>برمجة يومية، قوي ورخيص</td>
    </tr>
    <tr>
      <td>الاستدلال (think/longContext)</td>
      <td><code class="language-plaintext highlighter-rouge">MiniMax-M2.7</code></td>
      <td>MiniMax</td>
      <td>تفكير منفصل، كلفة منخفضة جداً لكل رمز</td>
    </tr>
    <tr>
      <td>الوكيل الفرعي للبرمجة</td>
      <td><code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code></td>
      <td>Ollama Cloud</td>
      <td>للأدوار البرمجية الصعبة فقط</td>
    </tr>
  </tbody>
</table>

<p>‏<code class="language-plaintext highlighter-rouge">glm-5.2</code> هو حصان العمل؛ والاستدلال العميق والسياق الطويل فقط يذهبان إلى MiniMax، والدور البرمجي الصعب إلى Kimi.</p>

<hr />

<h2 id="التحقق--استدعينا-ولم-نفترض">التحقق — استدعينا ولم نفترض</h2>

<p>قبل كتابة أي إعداد، استدعينا النماذج الثلاثة مباشرةً. ولتجنّب اختلاق الأرقام فحصنا الاستجابات الفعلية، فظهرت ثلاث حقائق.</p>

<p><strong>أولاً، مفتاح Ollama Cloud واحد يغطي GLM وKimi معاً.</strong> أرجع كلٌّ من <code class="language-plaintext highlighter-rouge">glm-5.2</code> و<code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code> رمز HTTP 200 من <code class="language-plaintext highlighter-rouge">https://ollama.com/v1</code>. فـ Ollama Cloud يجمع عائلات GLM وKimi وDeepSeek وQwen خلف مفتاح واحد.</p>

<p><strong>ثانياً، مفتاح Kimi المنفرد كان ميتاً.</strong> أرجع مفتاح Moonshot المنفرد في <code class="language-plaintext highlighter-rouge">.env</code> رمز 401 (مصادقة غير صالحة) على moonshot.ai وmoonshot.cn ونقطة Anthropic المتوافقة على حدٍّ سواء. لحسن الحظ يمكن الوصول إلى Kimi K2 عبر <code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code> في Ollama Cloud، فلم يكن المفتاح الميت طريقاً مسدوداً.</p>

<p><strong>ثالثاً، اختيار نقطة MiniMax يحسم الجودة.</strong> عند الاستدعاء عبر النقطة المتوافقة مع OpenAI (<code class="language-plaintext highlighter-rouge">/v1/chat/completions</code>) يضمّن النموذج استدلاله داخل المتن بوسوم <code class="language-plaintext highlighter-rouge">&lt;think&gt;...&lt;/think&gt;</code>، وتعجز طبقة التحويل في CCR عن إزالتها فتتسرب إلى المستخدم (musistudio/claude-code-router#964). أما عند الاستدعاء عبر نقطة Anthropic الأصلية (<code class="language-plaintext highlighter-rouge">/anthropic/v1/messages</code>) فيُرجع النموذج نفسه كتلتي <code class="language-plaintext highlighter-rouge">thinking</code> و<code class="language-plaintext highlighter-rouge">text</code> نظيفتين.</p>

<p>البند الأخير علّة وجب إصلاحها لا سبباً لإسقاط MiniMax. والإصلاح مُضمَّن في الإعداد أدناه.</p>

<hr />

<h2 id="الإعداد--الأسرار-خارج-المستودع-والإعداد-كشيفرة">الإعداد — الأسرار خارج المستودع، والإعداد كشيفرة</h2>

<p>لا تُكتب المفاتيح مباشرةً في ملف الإعداد. سكربت مولِّد يقرأ <code class="language-plaintext highlighter-rouge">.env</code> في المستودع ويكتب <code class="language-plaintext highlighter-rouge">~/.claude-code-router/config.json</code>. فلا تبقى مفاتيح في المستودع، وتدوير المفتاح يعني فقط إعادة تشغيل السكربت.</p>

<p>الإعداد المُولَّد الأساسي:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"LOG"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
  </span><span class="nl">"HOST"</span><span class="p">:</span><span class="w"> </span><span class="s2">"127.0.0.1"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"PORT"</span><span class="p">:</span><span class="w"> </span><span class="mi">3456</span><span class="p">,</span><span class="w">
  </span><span class="nl">"API_TIMEOUT_MS"</span><span class="p">:</span><span class="w"> </span><span class="mi">1800000</span><span class="p">,</span><span class="w">
  </span><span class="nl">"Providers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://ollama.com/v1/chat/completions"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;OLLAMA_GLM_API_KEY&gt;"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"glm-5.2"</span><span class="p">,</span><span class="w"> </span><span class="s2">"kimi-k2.7-code"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"transformer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"use"</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="s2">"maxtoken"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"max_tokens"</span><span class="p">:</span><span class="w"> </span><span class="mi">16000</span><span class="w"> </span><span class="p">}]]</span><span class="w"> </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://api.minimax.io/anthropic/v1/messages"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;MINIMAX_API_KEY&gt;"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"MiniMax-M2.7"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"transformer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"use"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Anthropic"</span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">],</span><span class="w">
  </span><span class="nl">"Router"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"default"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"background"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"think"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax,MiniMax-M2.7"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"longContext"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax,MiniMax-M2.7"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"longContextThreshold"</span><span class="p">:</span><span class="w"> </span><span class="mi">60000</span><span class="p">,</span><span class="w">
    </span><span class="nl">"webSearch"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>السطران في مزوّد MiniMax هما ما يُصلِح تسرّب التفكير. وجِّه <code class="language-plaintext highlighter-rouge">api_base_url</code> إلى مسار Anthropic الأصلي واستخدم محوّل التمرير <code class="language-plaintext highlighter-rouge">Anthropic</code>، فيستجيب MiniMax بصيغة رسائل Anthropic (كتلتا <code class="language-plaintext highlighter-rouge">thinking</code> و<code class="language-plaintext highlighter-rouge">text</code>) منذ البداية. وعند إعادة الفحص عبر الوسيط كانت كتل الاستجابة <code class="language-plaintext highlighter-rouge">["thinking", "text"]</code> بلا أي تسرّب لـ <code class="language-plaintext highlighter-rouge">&lt;think&gt;</code>.</p>

<p>نماذج الاستدلال بطيئة الإخراج، لذا جُعِلت المهلة سخية (<code class="language-plaintext highlighter-rouge">1800000ms</code>)، ويحجز <code class="language-plaintext highlighter-rouge">maxtoken</code> مساحة إخراج كي لا تستنفد نماذج مثل GLM وKimi — التي تُخرِج الاستدلال أولاً — الميزانية قبل الإجابة.</p>

<p>تُوجَّه الوكلاء الفرعيون لا بالإعداد بل بوسم في مقدمة المُوجّه. لتفويض مهمة برمجية صعبة، أضِف في مقدمة المُوجّه <code class="language-plaintext highlighter-rouge">&lt;CCR-SUBAGENT-MODEL&gt;ollama,kimi-k2.7-code&lt;/CCR-SUBAGENT-MODEL&gt;</code>.</p>

<hr />

<h2 id="أين-وكيف-تتصل">أين وكيف تتصل</h2>

<p>نقطة الاتصال واحدة. ابدأ جلسة بـ <code class="language-plaintext highlighter-rouge">ccr code</code> في مستودع عملك، فتُوجَّه حركة تلك الجلسة الرئيسية والفرعية كلها عبر الوسيط وفق الجدول أعلاه. أما <code class="language-plaintext highlighter-rouge">claude</code> الأصلي فيتصل مباشرةً بـ Anthropic، فلا يتأثر.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># توليد الإعداد ثم تشغيل الموجِّه</span>
python3 scripts/ccr/gen_ccr_config.py <span class="o">&amp;&amp;</span> ccr restart

<span class="c"># بدء جلسة موجَّهة للتكلفة (هذه هي نقطة الاتصال)</span>
ccr code

<span class="c"># بدّل النماذج حسب المهمة داخل الجلسة</span>
/model ollama,kimi-k2.7-code     <span class="c"># دور برمجي صعب</span>
/model minimax,MiniMax-M2.7      <span class="c"># دور استدلال عميق</span>
/model ollama,glm-5.2            <span class="c"># برمجة يومية</span>
</code></pre></div></div>

<p>من حيث كفاءة التكلفة، النمط المُوصى به هجين. شغّل الأعمال الكثيفة والمتكررة وغير التفاعلية (توليد الاختبارات، إعادة الهيكلة الجماعية، تحليل السجلات، الترجمة، استكشاف الكود) تحت <code class="language-plaintext highlighter-rouge">ccr code</code> لخفض التكلفة، وأبقِ الأعمال التي تتطلب حكماً (قرارات معمارية، تصحيح دقيق) على جلسة <code class="language-plaintext highlighter-rouge">claude</code> الاشتراكية الأصلية. فنقل كل شيء إلى الجلسة الموجَّهة يجعل GLM حلقتك الرئيسية، وقد يخفض الجودة في المهام الصعبة.</p>

<hr />

<h2 id="كفاءة-التكلفة--قياس-مستمر-مقابل-sonnet">كفاءة التكلفة — قياس مستمر مقابل Sonnet</h2>

<p>سبب وجود هذا الإعداد هو التكلفة. لذا بدل أن ندّعي أنه “أرخص”، نقيس.</p>

<p>الأسعار المُتحقَّق منها في 2026-06-24 (بالدولار لكل مليون رمز):</p>

<table>
  <thead>
    <tr>
      <th>النموذج</th>
      <th>الإدخال</th>
      <th>الإخراج</th>
      <th>نمط الفوترة</th>
      <th>مقابل Sonnet</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Claude Sonnet 4.6 (المرجع)</td>
      <td>$3.00</td>
      <td>$15.00</td>
      <td>لكل رمز</td>
      <td>1.0×</td>
    </tr>
    <tr>
      <td>MiniMax-M2.7</td>
      <td>$0.24</td>
      <td>$0.96</td>
      <td>لكل رمز</td>
      <td>~0.07×</td>
    </tr>
    <tr>
      <td>glm-5.2 / kimi-k2.7-code</td>
      <td>—</td>
      <td>—</td>
      <td>اشتراك $20/شهر (Pro)</td>
      <td>يعتمد على الاستخدام</td>
    </tr>
  </tbody>
</table>

<p>‏MiniMax-M2.7 نحو 7-8% من سعر Sonnet لكل رمز، فهو دوماً أرخص بفارق كبير. أما Ollama Cloud فاشتراك شهري ثابت لا تسعير لكل رمز. سعره الفعلي = <code class="language-plaintext highlighter-rouge">الرسم الشهري ÷ الرموز المستخدمة شهرياً</code>، وعند الاستخدام المنخفض يكون الرسم الثابت $20 خسارة. وبمعدل مخلوط $9/M، عليك تجاوز <strong>نحو 2.2 مليون رمز شهرياً</strong> قبل أن يتفوق على Sonnet.</p>

<p>نقطة التعادل هذه هدف قياس لا تخمين. تسجّل سجلات CCR النموذج المُوجَّه ورموز الإدخال/الإخراج لكل طلب. وسكربت قياس يجمعها، فيحسب نسبة التكلفة الفعلية إلى تكلفة Sonnet المكافئة للنماذج بالرمز، والتكلفة الشهرية المتوقّعة لـ Sonnet مقابل رسم الاشتراك للنماذج بالاشتراك. وتتراكم النتائج في ملف تاريخي لتتبّع الاتجاه، والتحسّن يعني انخفاض النسبة مع الوقت.</p>

<p>تعمل الحلقة مرة يومياً عبر launchd. ولا يكون Claude داخل الحلقة؛ بل يعمل سكربت بسيط فقط على cron، فتكون كلفة القياس نفسها صفراً. وإذا وُجِد نموذج بالرمز أغلى من Sonnet يُطلَق تنبيه إلى Slack. أما النموذج بالاشتراك دون نقطة التعادل (استخدام ناقص) فيُسجَّل دون تنبيه، تفادياً للضجيج في مرحلة الانطلاق.</p>

<p>قواعد الإجراء مرتبطة بالقياس. إذا بلغت نسبة نموذج بالرمز 1.0 أو أكثر (أغلى من Sonnet) يُزال فوراً من التوجيه. وإذا بقي نموذج بالاشتراك دون الاستخدام أشهراً، خفّض الخطة أو انقل ذلك المسار إلى نموذج رخيص بالرمز. وعند تغيّر الأسعار يكفي تحديث ملف جدول الأسعار لينعكس في التشغيل التالي.</p>

<hr />

<h2 id="منظور-منصة-thakicloud">منظور منصة ThakiCloud</h2>

<p>ينسجم نموذج التوجيه هذا طبيعياً مع البنية التي تشغّلها ThakiCloud فعلاً.</p>

<p><strong>أمن الكود.</strong> في البيئات التي لا يمكن أن يغادر فيها الكود المصدري (المالية، القطاع العام، الرعاية الصحية)، يكفي تبديل <code class="language-plaintext highlighter-rouge">default</code> في الإعداد أعلاه إلى نقطة vLLM داخلية. فتحتفظ بقابلية استخدام Claude Code بينما لا تغادر المُوجّهات والكود قط. وإعداد النماذج الخارجية هنا للتحقق من التكلفة؛ ضع خدمة GPU الداخلية في الهيكل نفسه فتحصل على النسخة المحلية.</p>

<p><strong>التحكم في التكلفة.</strong> التوجيه حسب المهمة هو توجيه حسب التكلفة. أرسِل الطلبات عالية التكرار منخفضة الصعوبة إلى نماذج رخيصة واحتفظ بالنماذج العليا للاستدلال الصعب، فتضيّق الاستخدام المكلف إلى حيث يلزم فعلاً، وتثبت حلقة القياس الأثر بالأرقام.</p>

<p><strong>السياسة كشيفرة.</strong> المزوّدون وقواعد التوجيه وجدول الأسعار ومعايير القياس كلها مُدارة كملفات نصية مُودَعة في المستودع. وتبقى المفاتيح وحدها في <code class="language-plaintext highlighter-rouge">.env</code> ويُعاد إنتاج الإعداد بمولِّد، فيُستعاد الإعداد نفسه على أي جهاز.</p>

<hr />

<h2 id="الحدود-والاعتراضات">الحدود والاعتراضات</h2>

<p>الموجِّه لا يحل كل شيء. عدة نقاط تستحق نظرة باردة.</p>

<ul>
  <li><strong>فجوة الجودة</strong>: قيمة التوجيه تتبع جودة النموذج الخلفي. فالنماذج المفتوحة لا تجاري دوماً النماذج المغلقة العليا في إعادة الهيكلة المعقدة متعددة الخطوات أو التصحيح الدقيق. ومن هنا توصية النمط الهجين.</li>
  <li><strong>موثوقية استدعاء الأدوات</strong>: يعتمد Claude Code كثيراً على استدعاء الأدوات. وقد تهتز صيغ استدعاء الأدوات عبر طبقة التحويل المتوافقة مع OpenAI، فهي آمنة لوكلاء الاستكشاف/التلخيص لكنها تستدعي توسعاً تدريجياً لوكلاء التحرير/التنفيذ.</li>
  <li><strong>فخ الاشتراك</strong>: Ollama Cloud بسعر ثابت، فالاستخدام المنخفض خسارة. ودون نقطة التعادل يكون Sonnet أرخص ببساطة. وحلقة القياس تراقب هذه النقطة بالضبط.</li>
  <li><strong>الوسيط نقطة فشل واحدة</strong>: تمر الحركة الرئيسية أيضاً عبر CCR، فإذا مات الوسيط تتوقف الجلسة. والبديل هو <code class="language-plaintext highlighter-rouge">claude</code> الأصلي.</li>
  <li><strong>فخ تأطير “المجاني”</strong>: تروّج بعض النسخ المعدّلة لإزالة القياس عن بُعد أو حواجز الأمان بوصفها “مجانية”. وهذا اتجاه لا تستطيع شركة تأييده. والقيمة التي نأخذها ليست المجانية بل التحكم — نحن من يقرّر أي طلب يذهب إلى أي نموذج، ونحن من يقيس التكلفة.</li>
</ul>

<p>في الخلاصة، CCR ليس حيلة سحرية لخفض التكلفة بل أداة تحكم في التوجيه. وحين يُدمَج مع مجموعة نماذج مُتحقَّق منها، وإصلاحات لعلل حقيقية مثل تسرّب التفكير، وقياس مستمر مقابل Sonnet، يصبح مكسباً حقيقياً على محوري الأمان والتكلفة.</p>

<hr />

<h2 id="المصادر">المصادر</h2>

<ul>
  <li>claude-code-router (musistudio): <a href="https://github.com/musistudio/claude-code-router">https://github.com/musistudio/claude-code-router</a></li>
  <li>مشكلة تسرّب تفكير MiniMax: <a href="https://github.com/musistudio/claude-code-router/issues/964">claude-code-router#964</a></li>
  <li>سعر MiniMax M2.7: <a href="https://openrouter.ai/minimax/minimax-m2.7">openrouter.ai/minimax/minimax-m2.7</a></li>
  <li>أسعار Ollama Cloud: <a href="https://ollama.com/pricing">ollama.com/pricing</a></li>
  <li>أسعار Claude API: <a href="https://platform.claude.com/docs/en/about-claude/pricing">platform.claude.com/docs pricing</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="llmops" /><category term="claude-code" /><category term="model-routing" /><category term="cost-optimization" /><category term="ollama" /><category term="minimax" /><category term="on-premise" /><summary type="html"><![CDATA[توجيه حركة Claude Code عبر glm-5.2 وMiniMax-M2.7 وKimi K2 باستخدام claude-code-router. سجل عملي للتحقق من النماذج الثلاثة مباشرةً، وإصلاح تسرّب تفكير MiniMax، وبناء حلقة تتحقق باستمرار من أن كل نموذج موجَّه أرخص من Sonnet.]]></summary></entry><entry xml:lang="ar"><title type="html">ربط Claude Code بالنماذج المستضافة ذاتياً باستخدام free-claude-code: اختبار ميداني لبروكسي التوجيه بين 17 مزوداً</title><link href="https://thakicloud.github.io/ar/llmops/free-claude-code-router/" rel="alternate" type="text/html" title="ربط Claude Code بالنماذج المستضافة ذاتياً باستخدام free-claude-code: اختبار ميداني لبروكسي التوجيه بين 17 مزوداً" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/ar/llmops/free-claude-code-router</id><content type="html" xml:base="https://thakicloud.github.io/ar/llmops/free-claude-code-router/"><![CDATA[<h2 id="نظرة-عامة">نظرة عامة</h2>

<p>Claude Code عميل برمجي قوي. غير أن بنيته القائمة على توجيه كل طلب مباشرةً إلى Anthropic API تُقيّد المؤسسات الراغبة في ضبط التكاليف أو إبقاء البيانات داخل حدودها. يعالج مشروع <code class="language-plaintext highlighter-rouge">free-claude-code</code> الذي شهد انتشاراً واسعاً مؤخراً هذه النقطة بالذات؛ إذ يُمثّل طبقة بروكسي تعترض حركة مرور Claude Code وتعيد توجيهها إلى 17 مزوداً مختلفاً. وهو مشروع مرخص بـ MIT يحمل 36.7k نجمة على GitHub و5.7k تفرع و712 إيداعاً.</p>

<p>شعار المشروع التسويقي هو “Claude Code مجاناً إلى الأبد.” يعمل النهج عبر تحويل حركة المرور نحو مزودين ذوي فئة مجانية أو منخفضة التكلفة، وهذا الإطار مبالغ فيه إلى حد ما وينطوي على منطقة رمادية من حيث شروط الخدمة. لذا يركز هذا المقال لا على زاوية “المجاني”، بل على ما يعنيه هذا الأداة للمؤسسات كـ ThakiCloud التي <strong>تخدم نماذجها الخاصة على Kubernetes وتريد ربط Claude Code ببنيتها التحتية الخاصة</strong>. النقاط الجوهرية هي أن الكود والمطالبات لا تغادر حدود المستأجر، وتختفي فواتير السحابة المحسوبة لكل رمز، ولا حاجة لتعديل جانب العميل لأن نقطة النهاية متوافقة مع Anthropic.</p>

<blockquote>
  <p>ملاحظة: ركّز المقال السابق “توجيه Claude Code إلى النماذج الداخلية - claude-code-router” على <strong>المراجحة في التكاليف</strong> بين نماذج السحابة (glm وMiniMax وKimi). يتناول هذا المقال أداةً مختلفة (<code class="language-plaintext highlighter-rouge">free-claude-code</code>)، ويعالج الاتصال بـ <strong>الخلفيات المستضافة ذاتياً (Ollama وvLLM)</strong> لا بالسحابة، إلى جانب مخاطر النشر التي كشفها هذا المسار.</p>
</blockquote>

<h2 id="ما-الذي-يفعله-هذا-الأداة">ما الذي يفعله هذا الأداة</h2>

<p><code class="language-plaintext highlighter-rouge">free-claude-code</code> خادم بروكسي محلي يستقبل الطلبات التي يرسلها Claude Code (وCodex). ميزته الجوهرية أنه <strong>يحاكي نقطة نهاية متوافقة مع Anthropic بشكل كامل</strong>. من منظور العميل، لا يمكن تمييزه عن Anthropic API الحقيقية، مما يتيح تبديل الخلفية دون تغيير سطر واحد في Claude Code.</p>

<p>الخادم مكتوب بـ FastAPI ويكشف نقاط النهاية التالية:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">/v1/messages</code> - متوافق مع Anthropic Messages API (المسار الرئيسي لـ Claude Code)</li>
  <li><code class="language-plaintext highlighter-rouge">/v1/models</code> - قائمة النماذج</li>
  <li><code class="language-plaintext highlighter-rouge">/v1/responses</code> - متوافق مع OpenAI Responses API (لـ Codex؛ يُحوَّل داخلياً إلى Messages)</li>
</ul>

<p>عند وصول طلب، يقرر <strong>موجّه النماذج</strong> أي مزود يرسل إليه الطلب، ثم يحوّل <strong>المُوحِّد</strong> كتل التفكير وأدوات الاستدعاء واستجابات الخطأ إلى الشكل الذي يتوقعه كل عميل. نظراً لاختلاف صيغ الاستجابة بين المزودين، تكمن في طبقة التوحيد هذه الصعوبة الحقيقية.</p>

<p>لنتوسع قليلاً في سبب صعوبة التوحيد: يفترض Claude Code بنية استجابة خاصة بـ Anthropic؛ فخطوات الاستدلال تأتي ككتل <code class="language-plaintext highlighter-rouge">thinking</code>، واستدعاءات الأدوات ككتل محتوى <code class="language-plaintext highlighter-rouge">tool_use</code>. لكن DeepSeek يُصدر الاستدلال كحقل منفصل، في حين تُعيد المزودين المتوافقين مع OpenAI استدعاءات الأدوات كمصفوفة <code class="language-plaintext highlighter-rouge">tool_calls</code>. المعنى واحد وهو “استُدعيت أداة”، لكن صيغة السلك تختلف في كل حالة. يجب على المُوحِّد استيعاب هذه الفوارق وضمان حصول Claude Code على استجابات بشكل متطابق بغض النظر عن الخلفية المستخدمة. يذهب مسار Codex (<code class="language-plaintext highlighter-rouge">/v1/responses</code>) خطوة أبعد بتحويل طلبات OpenAI Responses داخلياً إلى Anthropic Messages قبل مشاركة الموجّه والمُوحِّد ومحوّلات المزودين ذاتها. أي أن تحويل البروتوكول يجري في الاتجاهين — وهذا هو الفارق الجوهري بين البروكسي العكسي البسيط وبروكسي التوجيه.</p>

<p><img src="/assets/images/free-claude-code-router-diagram.png" alt="بنية توجيه free-claude-code" />
<em>الشكل 1. يستقبل بروكسي FastAPI حركة المرور المتوافقة مع Anthropic من Claude Code ويوزعها على 17 مزوداً. من منظور ThakiCloud، المسارات الجوهرية هي الخلفيات المستضافة ذاتياً على اليمين (Ollama وLM Studio وvLLM).</em></p>

<p>المزودون المدعومون 17 مزوداً. على الجانب السحابي: NVIDIA NIM وOpenRouter وGoogle AI Studio (Gemini) وDeepSeek وMistral La Plateforme وMistral Codestral وOpenCode Zen وOpenCode Go وWafer وKimi وCerebras وGroq وFireworks وZ.ai. على <strong>جانب الاستضافة الذاتية: LM Studio وllama.cpp وOllama</strong>. الثلاثة الأخيرة هي ذات الأهمية من منظور ThakiCloud. إذ يكشف Ollama وllama.cpp نقاط نهاية متوافقة مع OpenAI، مما يعني أن خادم vLLM المنشور بالطريقة ذاتها على Kubernetes يمكن ربطه بنفس الأسلوب.</p>

<p>يتحكم في توجيه الفئات عبر متغيرات البيئة. يحدد كل من <code class="language-plaintext highlighter-rouge">MODEL_OPUS</code> و<code class="language-plaintext highlighter-rouge">MODEL_SONNET</code> و<code class="language-plaintext highlighter-rouge">MODEL_HAIKU</code> أي نموذج يُوجَّه إليه كل فئة من فئات Claude الثلاث؛ وعند غياب التحديد يُستخدم النموذج الاحتياطي <code class="language-plaintext highlighter-rouge">MODEL</code>. يتيح هذا نشراً متدرجاً، كتوجيه حركة مرور Haiku الخفيفة إلى نماذج صغيرة والحركة الثقيلة من Opus إلى نماذج أكبر.</p>

<h2 id="التثبيت-والتكامل">التثبيت والتكامل</h2>

<p>مسار التثبيت الرسمي هو سطر أوامر واحد:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># macOS / Linux</span>
curl <span class="nt">-fsSL</span> <span class="s2">"https://github.com/Alishahryar1/free-claude-code/blob/main/scripts/install.sh?raw=1"</span> | sh

<span class="c"># Windows PowerShell</span>
irm <span class="s2">"https://github.com/Alishahryar1/free-claude-code/blob/main/scripts/install.ps1?raw=1"</span> | iex
</code></pre></div></div>

<p>بدلاً من سطر الأوامر، تحققت من الحزمة بتثبيتها مباشرةً في بيئة اختبار معزولة، حفاظاً على سلامة البيئة الافتراضية المشتركة وفق قواعد وقت تشغيل Python في ThakiCloud.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># شجرة عمل معزولة + venv مؤقت (البيئة المشتركة .venv على 3.12.8 وستتعارض)</span>
uv venv <span class="nt">--python</span> 3.14 .expenv
<span class="nv">VIRTUAL_ENV</span><span class="o">=</span>.expenv uv pip <span class="nb">install</span> <span class="s2">"git+https://github.com/Alishahryar1/free-claude-code.git"</span>
</code></pre></div></div>

<p>تُثبَّت الحزمة ذاتها بنظافة. تُحلّ التبعيات مثل fastapi وuvicorn وhttpx وpydantic وopenai وloguru بنجاح، وتُنشأ سكريبتات وحدة التحكم مثل <code class="language-plaintext highlighter-rouge">fcc-server</code> و<code class="language-plaintext highlighter-rouge">fcc-init</code> و<code class="language-plaintext highlighter-rouge">fcc-claude</code>. بعد تشغيل الخادم، يُوجَّه Claude Code نحو البروكسي على النحو الآتي:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fcc-server            <span class="c"># تشغيل بروكسي FastAPI (الافتراضي http://127.0.0.1:8082)</span>
<span class="c"># مثال على خلفية مستضافة ذاتياً (Ollama):</span>
<span class="c">#   MODEL_HAIKU=ollama/llama3.2:3b</span>
<span class="c">#   MODEL_SONNET=ollama/qwen2.5:7b</span>
<span class="c"># حدد عنوان URL الأساسي لتوجيه Claude Code نحو البروكسي ثم استخدمه كالمعتاد</span>
</code></pre></div></div>

<p>واجهة الإدارة متاحة على <code class="language-plaintext highlighter-rouge">http://127.0.0.1:8082/admin</code> وتكون محدودة بحلقة الاسترداد فقط. تُدار هنا مفاتيح المزودين وتوجيه النماذج وإعدادات الرسائل والصوت.</p>

<h2 id="نتائج-التجربة-الفعلية">نتائج التجربة الفعلية</h2>

<p>خلال عملية التحقق، واجهت <strong>نقطة أعاقت إعادة الإنتاج</strong>، وأسجلها كما هي. عدم اختلاق الأرقام مبدأ راسخ في هذا التقرير.</p>

<h3 id="حاجز-التشغيل-الاشتراط-الصارم-بـ-python-314">حاجز التشغيل: الاشتراط الصارم بـ Python 3.14</h3>

<p>يُثبّت <code class="language-plaintext highlighter-rouge">free-claude-code</code> الإصدار v2.3.14 اشتراط <code class="language-plaintext highlighter-rouge">requires-python = "&gt;=3.14.0"</code> بشكل صارم. Python 3.14 هو الإصدار الأحدث الذي صدر رسمياً في أكتوبر 2025 فحسب. المشكلة أن الإصدار 3.14 الوحيد المتاح في بيئة الاختبار كان بناء ألفا (3.14.0a7). تشغيل <code class="language-plaintext highlighter-rouge">fcc-server</code> على هذا الإصدار الألفا يفشل بالخطأ التالي:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ImportError: cannot import name 'get_annotate_from_class_namespace'
from 'annotationlib'
</code></pre></div></div>

<p>يحدث هذا التعارض لأن pydantic المثبّت يتوقع واجهة <code class="language-plaintext highlighter-rouge">annotationlib</code> الخاصة بالإصدار النهائي 3.14، لكن الرمز المطلوب غير موجود بعد في الإصدار الألفا المبكر. حاولت عندئذٍ التشغيل قسراً على الإصدار المستقر الأدنى (3.13)، لكن التثبيت ذاته يُرفض بسبب الاشتراط الصارم في بيانات الحزمة:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>free-claude-code==2.3.14 cannot be used ... your requirements are unsatisfiable.
</code></pre></div></div>

<p>الخلاصة واضحة: <strong>في البيئات التي تفتقر إلى Python 3.14 المستقر، لن يعمل هذا البروكسي أبداً.</strong> فشل محاولة إعادة الإنتاج: الحزمة تشترط Python 3.14 الصادر حديثاً، لكن الإصدار 3.14 الوحيد المتاح ألفا يتعارض مع pydantic المثبّت. هذه ليست عيباً في الأداة بقدر ما هي مشكلة <strong>تثبيت إصدار متعجّل</strong> يتعارض مع واقع بيئات الإنتاج التي تبقى في الغالب على 3.11–3.12.</p>

<h3 id="القياس-المباشر-لمسار-التوجيه-المستضاف-ذاتياً">القياس المباشر لمسار التوجيه المستضاف ذاتياً</h3>

<p>رغم أن البروكسي نفسه لم يُشغَّل، فإن <strong>الآلية</strong> التي تستخدمها هذه الأداة لاستدعاء مزود <code class="language-plaintext highlighter-rouge">ollama</code> هي نقطة النهاية المتوافقة مع OpenAI. لذا قست هذا المسار باستدعاء Ollama المحلي مباشرةً. هذه أرقام أداء التوجيه للخلفية ذاتها دون تضمين الحمل الإضافي للبروكسي الذي ستضيفه fcc. نتائج تعيين فئات Claude الثلاث لنماذج محلية كالآتي (Apple Silicon، مطالبة متطابقة، حد 64 رمزاً):</p>

<p><img src="/assets/images/free-claude-code-router-results.png" alt="نتائج قياس التوجيه المستضاف ذاتياً" />
<em>الشكل 2. التأخر ومعدل المعالجة عند توجيه فئات Claude إلى نماذج Ollama المحلية. qwen3:8b المُدرج في مسار opus نموذج تفكير يُصدر رموز استدلال مطوّلة مما يزيد الوقت بشكل ملحوظ.</em></p>

<table>
  <thead>
    <tr>
      <th>التوجيه</th>
      <th>النموذج</th>
      <th>التأخر</th>
      <th>رموز الإكمال</th>
      <th>معدل المعالجة</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>haiku</td>
      <td>llama3.2:3b</td>
      <td>0.49s</td>
      <td>33</td>
      <td>67.3 tok/s</td>
    </tr>
    <tr>
      <td>sonnet</td>
      <td>qwen2.5:7b</td>
      <td>0.56s</td>
      <td>20</td>
      <td>35.7 tok/s</td>
    </tr>
    <tr>
      <td>opus</td>
      <td>qwen3:8b</td>
      <td>8.12s</td>
      <td>281</td>
      <td>34.6 tok/s</td>
    </tr>
  </tbody>
</table>

<p>النموذج الصغير (llama3.2:3b) ينهي استجابته في أقل من 0.5 ثانية، وهو سرعة كافية لحركة مرور بديلة عن Haiku. كذلك qwen2.5:7b عند 0.56 ثانية عملي للاستخدام. في المقابل، استغرق qwen3:8b المُدرج في مسار opus 8.12 ثانية، لأن نموذج التفكير يُصدر أولاً 281 رمز استدلال. معدل المعالجة (34.6 tok/s) طبيعي في حد ذاته، لكن القياس أكد أن <strong>توظيف نموذج استدلالي في فئة ثقيلة يُفجّر عدد الرموز ويزيد التأخر المُدرَك بشكل كبير</strong>. درس عملي: عند تصميم تعيينات الفئات، ينبغي مراعاة ميل النموذج لتوليد رموز الاستدلال.</p>

<h2 id="التطبيق-والدلالات-لمنصة-thakicloud-saas-للذكاء-الاصطناعيتعلم-الآلة-على-kubernetes">التطبيق والدلالات لمنصة ThakiCloud SaaS للذكاء الاصطناعي/تعلم الآلة على Kubernetes</h2>

<p>القيمة الحقيقية لهذه الأداة ليست في “المجانية” بل في <strong>نمط الاتصال</strong>. بمجرد إدراج بروكسي متوافق مع Anthropic كطبقة وسيطة، يمكن إرفاق عملاء تجاريين كـ Claude Code مباشرةً ببنيتنا التحتية.</p>

<p>تُجدول ThakiCloud وحدات GPU باستخدام Kueue وتُقدّم النماذج عبر vLLM على Kubernetes. نظراً لأن vLLM يوفر نقطة نهاية متوافقة مع OpenAI (<code class="language-plaintext highlighter-rouge">/v1/chat/completions</code>)، يمكن ربطها بمسار المزود المستضاف ذاتياً في <code class="language-plaintext highlighter-rouge">free-claude-code</code> بنفس الطريقة المتبعة مع Ollama أو llama.cpp. أسلوب الاتصال مشترك بين المزودين المستضافين ذاتياً: يُحدَّد عنوان URL الأساسي بنقطة نهاية خدمة vLLM في الكتلة، ويُضاف بادئة المزود إلى معرّف النموذج. تماماً كما تُكتب Ollama بالصيغة <code class="language-plaintext highlighter-rouge">ollama/llama3.2:3b</code>، يُضاف النموذج المُقدَّم على vLLM الداخلي لأهداف التوجيه باتباع قاعدة البادئة ذاتها. يُتيح ذلك:</p>

<ul>
  <li><strong>سيادة البيانات</strong>: لا يغادر الكود والمطالبات حدود المستأجر. هذا أمر جوهري في البيئات التنظيمية مثل النشر داخل المنشأة ومتطلبات الامتثال للأجهزة الحكومية.</li>
  <li><strong>تحوّل هيكل التكلفة</strong>: تتحوّل فوترة القياس لكل رمز إلى تكاليف GPU ثابتة. كلما ارتفع الاستخدام، تسارعت نقطة التعادل للتقديم الذاتي.</li>
  <li><strong>النشر المتدرج حسب الفئة</strong>: يمكن توجيه حركة مرور Haiku الخفيفة إلى نماذج صغيرة والأعمال الثقيلة إلى نماذج أكبر، مما يُحسّن الاستفادة من وحدات GPU. تُقدّم القياسات أعلاه الأرقام المرجعية لهذا النشر المتدرج.</li>
</ul>

<p>غير أن الأنسب بدلاً من اعتماد هذه الأداة كما هي هو <strong>استعارة نمط التوجيه المُتحقَّق منه فحسب</strong>. في بيئة متعددة المستأجرين، يجب أن يمتلك البروكسي مصادقة وعزلاً ومراقبةً لكل مستأجر، في حين تفترض واجهة إدارة <code class="language-plaintext highlighter-rouge">free-claude-code</code> مستخدماً واحداً في حلقة الاسترداد وهي قاصرة كما هي. الفكرة الكامنة في طبقة التوحيد المتوافقة مع Anthropic تستحق الاستعارة، لكن المصادقة والحصص والتسجيل يجب إعادة تطبيقها وفق معايير بوابتنا.</p>

<h2 id="القيود-والاعتراضات">القيود والاعتراضات</h2>

<p>أولاً، <strong>المنطقة الرمادية لشروط الخدمة</strong>. يعتمد إطار “Claude Code مجاناً” على التوجيه عبر مزودين ذوي فئة مجانية، مما قد يتعارض مع شروط خدمة كل منصة. في البيئات المؤسسية، الاستخدام المشروع والمستدام هو حصراً <strong>التوجيه إلى الخلفيات المملوكة (النماذج المُقدَّمة ذاتياً)</strong>. هذا هو سبب تأكيد هذا المقال على مسار الاستضافة الذاتية فحسب.</p>

<p>ثانياً، <strong>تثبيت الإصدار المتعجّل</strong>. يمنع الاشتراط الصارم بـ Python 3.14 التشغيلَ فوراً في البيئات التي تفتقر إلى وقت تشغيل مستقر كما رأينا. مع الأخذ بعين الاعتبار تكلفة ومخاطر ترقية صور حاويات الإنتاج إلى 3.14، فإن إدراج هذه الأداة مباشرةً في خط أنابيب النشر في الوقت الراهن ينطوي على عبء مفرط.</p>

<p>ثالثاً، <strong>لا يُضمن تكافؤ الجودة</strong>. استبدال Opus أو Sonnet من Claude بنماذج مختلفة لا يُبقي جودة البرمجة على حالها. التوجيه خيار يكسب فيه تكاليف أقل وسيادة بيانات مقابل التنازل عن جودة الاستجابة؛ وأي حركة مرور تُوجَّه إلى أي مكان يجب تحديده بالقياس وفق درجة صعوبة المهمة.</p>

<p>رابعاً، قياسات هذا التقرير هي <strong>أرقام استدعاء مباشر للخلفية دون المرور بالبروكسي</strong>. لا يشمل ذلك الحمل الإضافي للتوحيد والتوجيه في fcc. متى توافرت بيئة Python 3.14 المستقرة، أخطط لإعادة قياس التأخر ذهاباً وإياباً عبر البروكسي وإضافته تكملةً لهذه النتائج.</p>

<p>خلاصة القول، <code class="language-plaintext highlighter-rouge">free-claude-code</code> محفوف بالمخاطر إذا استُهلك بوصفه “اختراقاً مجانياً”، لكنه نقطة انطلاق ممتازة <strong>كمرجع مفتوح المصدر لأنماط التوجيه المتوافقة مع Anthropic</strong> عند تصميم ربط العملاء التجاريين ببنية الاستدلال المستضافة ذاتياً.</p>

<h2 id="المصادر">المصادر</h2>

<ul>
  <li>GitHub: <a href="https://github.com/Alishahryar1/free-claude-code">Alishahryar1/free-claude-code</a> (MIT, 36.7k stars, v2.3.14)</li>
  <li>بيانات القياس: استدعاءات مباشرة لنقطة النهاية المتوافقة مع OpenAI في Ollama المحلي (llama3.2:3b وqwen2.5:7b وqwen3:8b، Apple Silicon)</li>
  <li>مقال ذو صلة: مدونة ThakiCloud التقنية “توجيه Claude Code إلى النماذج الداخلية - claude-code-router”</li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="llmops" /><category term="free-claude-code" /><category term="Claude Code" /><category term="LLM Gateway" /><category term="Model Routing" /><category term="Ollama" /><category term="vLLM" /><category term="Self-Hosting" /><category term="FastAPI" /><category term="LLM Ops" /><summary type="html"><![CDATA[يعترض free-claude-code (36.7k نجمة) حركة مرور Claude Code عبر بروكسي FastAPI متوافق مع Anthropic ويوجهها إلى 17 مزوداً. يوثق هذا التقرير التوجيه المباشر إلى خلفية Ollama محلية مع قياسات للتأخر، ويسجل بصدق مخاطر النشر الناجمة عن اشتراط Python 3.14 بشكل صارم.]]></summary></entry><entry xml:lang="ar"><title type="html">تشكيلة Gemma 4 الكاملة: خمسة نماذج مفتوحة الأوزان برخصة Apache 2.0 ودليل التشغيل المحلي</title><link href="https://thakicloud.github.io/ar/owm/gemma-4-open-weight-lineup/" rel="alternate" type="text/html" title="تشكيلة Gemma 4 الكاملة: خمسة نماذج مفتوحة الأوزان برخصة Apache 2.0 ودليل التشغيل المحلي" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/ar/owm/gemma-4-open-weight-lineup</id><content type="html" xml:base="https://thakicloud.github.io/ar/owm/gemma-4-open-weight-lineup/"><![CDATA[<p>⏱️ <strong>وقت القراءة المقدر</strong>: 10 دقائق</p>

<p><img src="/assets/images/gemma-4-open-weight-lineup-hero.png" alt="مخطط مفاهيمي لتشكيلة Gemma 4" /></p>

<h2 id="نظرة-عامة-على-gemma-4">نظرة عامة على Gemma 4</h2>

<p>أصدرت Google DeepMind نموذج Gemma 4 في الثاني من أبريل 2026، وهو أذكى عائلة نماذج مفتوحة الأوزان أطلقتها Gemma حتى الآن. وتذكر Google أنه بُني على نفس الأبحاث والتقنيات التي يقوم عليها Gemini 3. بعبارة أخرى، يمكن اعتباره وصفة التدريب وراء نموذج رائد مغلق، مقطّرة إلى تشكيلة مفتوحة الأوزان.</p>

<p>من منظور ThakiCloud، يبرز تغييران في هذا الجيل. أولًا، انتقلت الرخصة إلى <strong>Apache 2.0</strong>. فخلافًا للأجيال السابقة من Gemma التي كانت تحمل سياسة استخدام منفصلة، يتبنى Gemma 4 رخصة مفتوحة المصدر قياسية ومتساهلة تجاريًا. ثانيًا، لا يُطرح بحجم واحد بل كتشكيلة من خمسة نماذج تمتد من <strong>الحافة (الهواتف) إلى وحدة معالجة رسومية واحدة على الخادم</strong>. أي أنه يمكنك اختيار هدف النشر حسب فئة الجهاز ضمن نفس عائلة النماذج.</p>

<p>بدلًا من التعمق في نموذج واحد، يهدف هذا المقال إلى <strong>مقارنة النماذج الخمسة دفعة واحدة وتوضيح أيها يُختار لكل حالة</strong>.</p>

<h2 id="تشكيلة-gemma-4-النماذج-الخمسة-كاملة">تشكيلة Gemma 4: النماذج الخمسة كاملة</h2>

<p>يتكوّن Gemma 4 من النماذج الخمسة التالية، منظمة حسب المعاملات والسياق والوسائط والبنية وفق بطاقة النموذج:</p>

<table>
  <thead>
    <tr>
      <th>النموذج</th>
      <th>المعاملات</th>
      <th>السياق</th>
      <th>وسائط الإدخال</th>
      <th>البنية</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>E2B</strong></td>
      <td>2.3B فعّالة (5.1B مع التضمينات)</td>
      <td>128K</td>
      <td>نص + صورة + صوت</td>
      <td>Dense</td>
    </tr>
    <tr>
      <td><strong>E4B</strong></td>
      <td>4.5B فعّالة (8B مع التضمينات)</td>
      <td>128K</td>
      <td>نص + صورة + صوت</td>
      <td>Dense</td>
    </tr>
    <tr>
      <td><strong>12B Unified</strong></td>
      <td>11.95B</td>
      <td>256K</td>
      <td>نص + صورة + صوت</td>
      <td>Dense</td>
    </tr>
    <tr>
      <td><strong>26B A4B</strong></td>
      <td>25.2B إجمالًا / 3.8B نشطة</td>
      <td>256K</td>
      <td>نص + صورة</td>
      <td>MoE (8 خبراء نشطون من 128)</td>
    </tr>
    <tr>
      <td><strong>31B Dense</strong></td>
      <td>30.7B</td>
      <td>256K</td>
      <td>نص + صورة</td>
      <td>Dense</td>
    </tr>
  </tbody>
</table>

<p>تُخرج النماذج الخمسة جميعها نصًا. ودعم إدخال الصوت متاح فقط في نماذج E2B وE4B و12B، بينما يتعامل 26B و31B مع النص والصورة.</p>

<p>يرمز حرف “E” في <code class="language-plaintext highlighter-rouge">E2B</code> و<code class="language-plaintext highlighter-rouge">E4B</code> إلى المعاملات الفعّالة (effective). وهو الحجم المبني على معاملات الحوسبة الفعلية باستثناء جدول التضمينات، والقيم الفعّالة هي الرقم الأكثر واقعية عند تقدير ميزانيات الذاكرة والحوسبة. ويستهدف هذان النموذجان مباشرةً الأجهزة الطرفية كالهواتف والحواسيب المحمولة.</p>

<p>جوهر التشكيلة هو <strong>تقسيم العمل بين النموذجين الأعلى: 26B A4B (MoE) و31B (Dense)</strong>.</p>

<ul>
  <li><strong>26B A4B</strong> هو نموذج Mixture-of-Experts. يضم 25.2B معاملًا إجماليًا لكنه يُفعّل نحو 3.8B فقط لكل رمز. ولا تزال الأوزان الكاملة بحاجة إلى الوجود في ذاكرة VRAM، لكن حوسبة كل رمز (FLOPs) تُحسب على أساس المعاملات النشطة، وهو ما <strong>يصب في صالح زمن الاستجابة والإنتاجية</strong>. ويناسب الخدمة التي تتطلب تمرير أعداد كبيرة من الطلبات بسرعة.</li>
  <li><strong>31B Dense</strong> نموذج كثيف قياسي يشارك فيه كل معامل في كل رمز. وهو موجّه نحو تعظيم الجودة وملاءمة الضبط الدقيق، وتضع Google نموذج 31B كسقف الجودة في التشكيلة.</li>
</ul>

<p>ووفقًا لـ Google، احتل 31B المركز الثالث بين النماذج المفتوحة عالميًا على لوحة Arena AI النصية، وحل 26B في المركز السادس، ووصفت التشكيلة بأنها “تنافس نماذج أكبر منها بعشرين ضعفًا”. وتتغير مثل هذه الترتيبات بمرور الوقت، لذا يُفضّل قراءتها كاتجاه (“كثافة ذكاء عالية مقارنة بفئتها”) لا كأرقام مطلقة.</p>

<h3 id="مسار-اختيار-النموذج">مسار اختيار النموذج</h3>

<pre><code class="language-mermaid">flowchart TD
    A[اختر نموذج Gemma 4] --&gt; B{هدف النشر؟}
    B --&gt;|هاتف/جهاز طرفي| C[E2B / E4B&lt;br/&gt;128K، دعم الصوت]
    B --&gt;|تشغيل محلي بوحدة واحدة| D{الأولوية؟}
    D --&gt;|الإنتاجية/زمن الاستجابة| E[26B A4B MoE&lt;br/&gt;نشطة 3.8B]
    D --&gt;|أعلى جودة/ضبط دقيق| F[31B Dense]
    D --&gt;|متعدد الوسائط + صوت + توازن| G[12B Unified&lt;br/&gt;256K، دعم الصوت]
</code></pre>

<h2 id="البنية-الانتباه-الهجين-وتعدد-الوسائط">البنية: الانتباه الهجين وتعدد الوسائط</h2>

<p>تتشارك نماذج Gemma 4 الخمسة آلية <strong>انتباه هجين</strong>. فهي تتناوب بين انتباه النافذة المنزلقة المحلية والانتباه العالمي الكامل. تُعالَج النطاقات القصيرة بثمن زهيد عبر النافذة المنزلقة، بينما يُدرَج الانتباه العالمي دوريًا لالتقاط ترابطات السياق الكامل، بهدف كبح كلفة الذاكرة والحوسبة في السياقات الطويلة. وهذا التصميم هو الخلفية وراء قدرة النماذج العليا (12B/26B/31B) على التعامل مع سياق 256K.</p>

<p>تعدد الوسائط هو الإعداد الافتراضي في هذا الجيل. تستقبل النماذج الخمسة جميعها النص والصورة كمدخل، وتتعامل الفئات الطرفية والمتوسطة (E2B/E4B/12B) مع إدخال الصوت أيضًا. كما أن الميزات الموجهة لسير عمل الوكلاء مدمجة أيضًا. فاستدعاء الدوال، وإخراج JSON المنظّم، وتعليمات النظام الأصلية مدعومة رسميًا، وتؤكد التشكيلة تحسينات في التخطيط متعدد الخطوات والاستدلال المنطقي مقارنة بالجيل السابق. وتاريخ قطع بيانات التدريب هو يناير 2025.</p>

<p>ودعم اللغات واسع: أكثر من 35 لغة جاهزة، وأكثر من 140 لغة على مستوى التدريب المسبق. وتتطلب الجودة الفعلية في التشغيل بالكورية تقييمًا مباشرًا، لكن التغطية متعددة اللغات نفسها واسعة.</p>

<h2 id="المعايير">المعايير</h2>

<p>فيما يلي المعايير التمثيلية التي نشرتها Google لنموذج 31B المضبوط على التعليمات، وفق بطاقة النموذج.</p>

<table>
  <thead>
    <tr>
      <th>المعيار</th>
      <th>31B (IT)</th>
      <th>المجال المقيس</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>MMLU-Pro</td>
      <td>85.2%</td>
      <td>المعرفة العامة والاستدلال</td>
    </tr>
    <tr>
      <td>GPQA Diamond</td>
      <td>84.3%</td>
      <td>الاستدلال العلمي بمستوى الدراسات العليا</td>
    </tr>
    <tr>
      <td>LiveCodeBench v6</td>
      <td>80.0%</td>
      <td>توليد الشيفرة</td>
    </tr>
    <tr>
      <td>MATH-Vision</td>
      <td>85.6%</td>
      <td>الرياضيات المعتمدة على الرؤية</td>
    </tr>
    <tr>
      <td>Codeforces (ELO)</td>
      <td>2150</td>
      <td>البرمجة التنافسية</td>
    </tr>
  </tbody>
</table>

<p>عند حجم 31B بعقدة واحدة، يُعد GPQA Diamond بنسبة 84.3% وMMLU-Pro بنسبة 85.2% في الصدارة بين النماذج المفتوحة الأوزان المماثلة. ومع ذلك، فالمعايير خاصة بالنسخة المضبوطة على التعليمات، ويجب التحقق من الأداء في المهام الواقعية بشكل منفصل. وعلى وجه الخصوص، لا تنعكس مهام الاستدلال والبرمجة بالكورية مباشرةً في المعايير العامة، لذا يُنصح بقياسها بمجموعة تقييم داخلية.</p>

<h2 id="الخدمة-والنشر">الخدمة والنشر</h2>

<p>أمّن Gemma 4 دعمًا واسعًا من منظومة الخدمة منذ الإطلاق. والمسارات الرسمية هي:</p>

<ul>
  <li><strong>خوادم الاستدلال</strong>: vLLM، SGLang، llama.cpp، Ollama، LM Studio، NVIDIA NIM</li>
  <li><strong>الأطر</strong>: Hugging Face Transformers / TRL / Transformers.js / Candle، Keras، MaxText، NeMo</li>
  <li><strong>الحافة/على الجهاز</strong>: LiteRT-LM، Cactus</li>
  <li><strong>الضبط الدقيق/التكميم</strong>: Unsloth، Tunix</li>
  <li><strong>بنية النشر</strong>: Docker، Baseten، Google Cloud (Vertex AI)</li>
</ul>

<p>يمكن تنزيل الأوزان من <a href="https://huggingface.co/collections/google/gemma-4">مجموعة google/gemma-4 على Hugging Face</a> وKaggle وOllama.</p>

<h3 id="متطلبات-وحدة-المعالجة-الرسومية-للتشغيل-المحلي-تقديري">متطلبات وحدة المعالجة الرسومية للتشغيل المحلي (تقديري)</h3>

<p>دليل تقريبي للنشر المحلي مبني على ذاكرة أوزان BF16 لكل نموذج. هذه تقديرات للأوزان تستثني ذاكرة KV وأعباء وقت التشغيل، لذا اترك هامشًا لطول السياق وعدد الطلبات المتزامنة في النشر الفعلي.</p>

<table>
  <thead>
    <tr>
      <th>النموذج</th>
      <th>أوزان BF16 (تقديري)</th>
      <th>نقطة بداية واقعية للتشغيل المحلي</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E2B / E4B</td>
      <td>نحو 5–16GB [تقديري]</td>
      <td>وحدة استهلاكية، حاسوب محمول، هاتف (LiteRT)</td>
    </tr>
    <tr>
      <td>12B Unified</td>
      <td>نحو 24GB [تقديري]</td>
      <td>وحدة 24GB واحدة (فئة RTX 4090/L4)، هامش عند التكميم</td>
    </tr>
    <tr>
      <td>26B A4B (MoE)</td>
      <td>نحو 50GB [تقديري]</td>
      <td>وحدة H100/A100 80GB واحدة</td>
    </tr>
    <tr>
      <td>31B Dense</td>
      <td>نحو 62GB [تقديري]</td>
      <td>وحدة H100/A100 80GB واحدة</td>
    </tr>
  </tbody>
</table>

<p>تكمن القوة العملية للتشكيلة في أن النموذجين الأعلى (26B و31B) يتسعان في <strong>وحدة معالجة رسومية واحدة بسعة 80GB</strong> بدقة BF16. أي أنه يمكنك تشغيل استدلال بمستوى متقدم على خادم واحد دون توازي موترات متعدد العقد، وهو ما يخفض كثيرًا حاجز التبني المحلي. وبميزانية وحدة أصغر، انزل إلى نموذج 12B أو إلى مسار مكمَّم (GGUF Q4/Q8). وبفضل طبيعته MoE التي تحسب فقط 3.8B النشطة، يتمتع 26B بأفضلية في الإنتاجية لكل رمز مقارنة بـ31B Dense عند نفس سعة VRAM.</p>

<h2 id="دلالات-للتطبيق-على-منصة-thakicloud-k8s-aiml-saas">دلالات للتطبيق على منصة ThakiCloud K8s AI/ML SaaS</h2>

<p>تتناغم تشكيلة Gemma 4 جيدًا مع استراتيجية الخدمة متعددة المستأجرين لدى ThakiCloud. وهي مهمة على ثلاث جبهات.</p>

<p><strong>Apache 2.0 يفتح حاجز التبني.</strong> إن إطلاق عائلة مفتوحة الأوزان بمستوى متقدم تحت رخصة Apache 2.0 القياسية أمر بالغ الأهمية للتبني المؤسسي والمحلي. إذ يمكنك دمجها في خدمات تجارية دون عبء مراجعة سياسة استخدام منفصلة، وتوزيع نواتج الضبط الدقيق بحرية. وهي عائلة نماذج يمكن اقتراحها مباشرةً على البيئات ذات الامتثال الصارم للترخيص، كالقطاع العام والمالي محليًا، وعلى العملاء المحليين الذين يشترطون الاستضافة الذاتية.</p>

<p><strong>التشكيلة نفسها تتوافق مع توجيه وحدات المعالجة الرسومية متعدد المستأجرين.</strong> تدير ThakiCloud حصص وحدات المعالجة الرسومية عبر Kueue وتخدم النماذج عبر vLLM. وتشكيلة Gemma 4 المكوّنة من خمسة نماذج بنية تتيح توجيه فئات النماذج ضمن عائلة واحدة لتلائم احتياجات المستأجرين (حساسية زمن الاستجابة، أولوية الجودة، استدلال الحافة). وجّه المحادثة/التلخيص الخفيف إلى 12B، والدفعات الحرجة للإنتاجية إلى 26B MoE، والاستدلال/البرمجة عالية الصعوبة إلى 31B، فتتمكن من تحسين ميزانية الوحدات حسب فئة المهمة مع الحفاظ على نفس المُرمِّز وصيغة المُوجِّه.</p>

<p><strong>الخدمة بوحدة 80GB واحدة تبسّط نموذج الكلفة.</strong> كون 26B و31B يتسعان في وحدة H100/A100 واحدة يبسّط تقدير كلفة مهام وحدات المعالجة الرسومية في Kueue. إذ تختفي أعباء الاتصال وتعقيد الجدولة في توازي الموترات متعدد العقد، فيمكنك التسعير بوضوح بنموذج وحدة مخصصة لكل مستأجر. وميزة 26B MoE بتفعيل 3.8B تعني أنه يستطيع استقبال طلبات متزامنة أكثر على نفس الوحدة، وهو ما يصب أيضًا في صالح كلفة الوحدة لكل طلب.</p>

<p>باختصار، يصلح Gemma 4 كعائلة نماذج مرجعية حين تقترح ThakiCloud نمط تشغيل “تشغيل محلي بوحدة واحدة + توجيه نماذج متعدد المستأجرين” على العملاء.</p>

<h2 id="القيود-والاعتراضات">القيود والاعتراضات</h2>

<p>من باب التوازن، تستحق بضع ملاحظات الذكر.</p>

<ul>
  <li><strong>الفجوة بين المعايير والاستخدام الواقعي.</strong> تتركز الأرقام المنشورة على المعايير المضبوطة على التعليمات وباللغة الإنجليزية. ويجب إعادة قياس المهام الكورية، خصوصًا دقة RAG واستدعاء أدوات الوكلاء، بمجموعة تقييم خاصة بك.</li>
  <li><strong>صعوبة تشغيل MoE.</strong> نموذج 26B A4B منخفض الحوسبة لكل رمز لكنه يجب أن يُبقي الأوزان الكاملة مقيمة في VRAM، ويؤثر توجيه الخبراء في كفاءة الدُفعات وأنماط الذاكرة. والقراءة المبسطة “إنه صغير لأن النشط 3.8B” قراءة محفوفة بالمخاطر.</li>
  <li><strong>عدم تماثل دعم الصوت.</strong> إدخال الصوت موجود فقط في E2B/E4B/12B. وإن أردت أعلى جودة (26B/31B) والصوت معًا، تنشأ مقايضة ضمن التشكيلة.</li>
  <li><strong>قطع التدريب في يناير 2025.</strong> المهام التي تحتاج أحدث المعلومات يجب تعزيزها بـRAG وتكامل الأدوات.</li>
</ul>

<p>ومع ذلك، فإن رخصة Apache 2.0، وجدوى الخدمة بوحدة واحدة، وتشكيلة تصل الحافة بالخادم، أسباب كافية لوضع Gemma 4 على رأس قائمة التقييم لأي مؤسسة تفكر في التشغيل المحلي والاستضافة الذاتية.</p>

<h2 id="المراجع">المراجع</h2>

<ul>
  <li><a href="https://blog.google/innovation-and-ai/technology/developers-tools/gemma-4/">مدونة الإعلان الرسمي عن Gemma 4 (Google)</a></li>
  <li><a href="https://ai.google.dev/gemma/docs/core/model_card_4">بطاقة نموذج Gemma 4 (Google AI for Developers)</a></li>
  <li><a href="https://ai.google.dev/gemma/docs/core">وثائق نظرة عامة على نموذج Gemma 4</a></li>
  <li><a href="https://huggingface.co/collections/google/gemma-4">مجموعة google/gemma-4 على Hugging Face</a></li>
  <li><a href="https://github.com/google-deepmind/gemma">مكتبة Gemma على GitHub من Google DeepMind</a></li>
  <li><a href="https://cloud.google.com/blog/products/ai-machine-learning/gemma-4-available-on-google-cloud">توفّر Gemma 4 على Google Cloud</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="owm" /><category term="gemma-4" /><category term="google-deepmind" /><category term="open-weight" /><category term="apache-2.0" /><category term="mixture-of-experts" /><category term="multimodal" /><category term="edge-ai" /><category term="vllm" /><category term="sglang" /><category term="on-premise" /><summary type="html"><![CDATA[أصدرت Google DeepMind نموذج Gemma 4 في أبريل 2026، وهو عائلة متعددة الوسائط مفتوحة الأوزان مكوّنة من خمسة نماذج تمتد من E2B إلى 31B. نشرح رخصة Apache 2.0، وسياق 256 ألف رمز، والفرق بين 26B MoE و31B Dense، وكيفية اختيار كل نموذج من منظور التشغيل المحلي.]]></summary></entry><entry xml:lang="en"><title type="html">Android Emulators in Containers - Building a Reproducible Device Farm on K8s with docker-android</title><link href="https://thakicloud.github.io/en/dev/docker-android-k8s-emulator/" rel="alternate" type="text/html" title="Android Emulators in Containers - Building a Reproducible Device Farm on K8s with docker-android" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/en/dev/docker-android-k8s-emulator</id><content type="html" xml:base="https://thakicloud.github.io/en/dev/docker-android-k8s-emulator/"><![CDATA[<pre><code class="language-mermaid">flowchart LR
    subgraph NODE["KVM-enabled K8s node / Pod"]
      EMU["Android emulator (QEMU + KVM, optional CUDA)"]
      KVM["/dev/kvm"]
    end
    KVM --&gt;|passthrough| EMU
    EMU --&gt; SVC["ADB Service"]
    SVC --&gt; CI["CI farm"]
    SVC --&gt; SCRCPY["scrcpy remote control"]
</code></pre>
<h2 id="overview">Overview</h2>

<p>Testing a mobile app requires Android devices. Managing a fleet of physical handsets is a maintenance burden, and installing a heavy emulator locally on every developer’s machine leads to environment drift and poor reproducibility. Those problems multiply when you try to include Android tests in a CI pipeline, because every build node needs a consistent emulator setup.</p>

<p><code class="language-plaintext highlighter-rouge">docker-android</code> (the HQarroum edition) solves this with containers. It packages an Android emulator in a minimal configuration, runs it headlessly, and exposes ADB and screen control over the network. A single container gives you a clean, consistent Android environment in seconds, making it a natural fit for CI/CD and automated testing.</p>

<p>This post verifies docker-android’s architecture and real requirements against the project documentation, then examines how a Kubernetes platform like ThakiCloud can handle this class of device workload. Android emulation is not central to our AI/ML platform, but the question of how to isolate and run privileged containers that need KVM device passthrough and GPU acceleration maps directly onto our infrastructure capabilities.</p>

<hr />

<h2 id="what-docker-android-is">What docker-android Is</h2>

<p>HQarroum’s docker-android bundles an Android emulator, KVM support, and JRE 11 into a compact Alpine-based image (current version 1.1.0). The design intent is clear: expose a fully functional, remotely controllable Android emulator with the smallest possible software footprint. Inside the image live the emulator itself, an ADB server for external access, and QEMU with libvirt.</p>

<p>Key characteristics:</p>

<ul>
  <li><strong>Minimal footprint</strong>: Alpine-based for size optimization. Building without the SDK and emulator produces a much smaller image.</li>
  <li><strong>Configurable</strong>: Android version, device type, and image variant are all selectable.</li>
  <li><strong>Built-in port forwarding</strong>: Emulator and ADB are exposed through the container network interface.</li>
  <li><strong>Headless</strong>: No GUI required, making it suitable for CI farms. Screens can be accessed remotely via <a href="https://github.com/Genymobile/scrcpy">scrcpy</a>.</li>
  <li><strong>Reproducibility</strong>: The emulator image resets on every restart, so each run starts from an identical state.</li>
</ul>

<p>The diagram above shows a hypothetical deployment of this container on ThakiCloud Kubernetes. The emulator runs in a pod on a KVM-enabled node with <code class="language-plaintext highlighter-rouge">/dev/kvm</code> passed through; the cuda variant is used when GPU acceleration is needed. ADB is exposed as a Service so CI farms and scrcpy clients can reach it.</p>

<hr />

<h2 id="installation-and-integration">Installation and Integration</h2>

<p>The default build bundles the Android SDK, platform tools, and emulator into the image. Bringing everything up with docker-compose looks like this:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Basic emulator</span>
docker compose up android-emulator

<span class="c"># GPU acceleration</span>
docker compose up android-emulator-cuda

<span class="c"># GPU acceleration + Google Play Store</span>
docker compose up android-emulator-cuda-store
</code></pre></div></div>

<p>You can also build directly with Docker:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">-t</span> android-emulator <span class="nb">.</span>
</code></pre></div></div>

<p>After building the image, run the container with the KVM device mounted. Using a Play Store image requires the emulator and client to share the same <code class="language-plaintext highlighter-rouge">adbkey</code>; generate it with <code class="language-plaintext highlighter-rouge">adb keygen adbkey</code> and place it in the <code class="language-plaintext highlighter-rouge">./keys</code> directory.</p>

<p>Image size varies considerably by build variant. The comparison table from the repository documentation:</p>

<table>
  <thead>
    <tr>
      <th>Build variant</th>
      <th>Uncompressed</th>
      <th>Compressed</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>API 33 + emulator</td>
      <td>5.84 GB</td>
      <td>1.97 GB</td>
    </tr>
    <tr>
      <td>API 32 + emulator</td>
      <td>5.89 GB</td>
      <td>1.93 GB</td>
    </tr>
    <tr>
      <td>API 28 + emulator</td>
      <td>4.29 GB</td>
      <td>1.46 GB</td>
    </tr>
    <tr>
      <td>Without SDK/emulator</td>
      <td>414 MB</td>
      <td>138 MB</td>
    </tr>
  </tbody>
</table>

<p>Images that include the emulator are over 1.5 GB even compressed. When distributing across many nodes, registry bandwidth and node disk capacity both need to be factored in.</p>

<hr />

<h2 id="verifying-actual-behavior">Verifying Actual Behavior</h2>

<p>This post does not include a verified container boot. Honest record: could not boot here (no Docker daemon on the work host, and macOS provides no <code class="language-plaintext highlighter-rouge">/dev/kvm</code>). docker-android requires KVM hardware acceleration, so real operation is only possible on a Linux host or a KVM node with nested virtualization enabled.</p>

<p>What we could verify came directly from the repository documentation. The image size comparison table above reflects numbers stated in the docs; build variants, compose service names, and KVM mount requirements are all documentation-based. Figures such as boot time or test throughput that we could not measure are not included. In an actual deployment, once KVM nodes are available, the right procedure is to measure container boot time, ADB connection latency, and maximum concurrent emulator count directly.</p>

<hr />

<h2 id="implications-for-the-thakicloud-k8s-aiml-saas-platform">Implications for the ThakiCloud K8s AI/ML SaaS Platform</h2>

<p>docker-android is not an AI/ML tool in itself. But the operational requirements it surfaces overlap precisely with what ThakiCloud does well.</p>

<p>First, <strong>isolation of device-passthrough workloads</strong>. An emulator is essentially a privileged container that requires <code class="language-plaintext highlighter-rouge">/dev/kvm</code>. Running this class of workload safely in a multi-tenant Kubernetes environment demands careful node selection, device plugins, and security contexts. ThakiCloud already queues GPUs through device plugins and Kueue; KVM passthrough can be handled with the same pattern.</p>

<p>Second, <strong>reproducible test farms</strong>. Packaging headless emulators as containers lets you scale clean environments horizontally across as many nodes as you need. Running many parallel Appium UI tests from a CI/CD pipeline is a textbook use case for Kubernetes job scheduling.</p>

<p>Third, looking further ahead, this extends naturally to <strong>on-device AI validation</strong>. Verifying the behavior of lightweight models or agents running on mobile devices at scale requires a device farm that can spin up many isolated Android environments and run regression tests automatically. This is not a core concern for our platform today, but as our multi-tenant GPU and device orchestration capabilities mature, a mobile AI QA farm of this kind becomes something we could offer on the same infrastructure.</p>

<p>In short, docker-android is not a product we are building, but it is a good case study in taming heavy container workloads that mix privilege, device passthrough, and GPU acceleration on Kubernetes. That is a concrete illustration of the general-purpose K8s orchestration capabilities ThakiCloud emphasizes.</p>

<hr />

<h2 id="limitations-and-counterarguments">Limitations and Counterarguments</h2>

<ul>
  <li><strong>Heavy dependencies</strong>: KVM hardware acceleration is non-negotiable. In environments without nested virtualization support, performance degrades sharply or the emulator does not boot at all. Cloud node selection becomes a hard constraint.</li>
  <li><strong>Image bloat</strong>: Emulator-inclusive images are several GB even compressed. Distributing across many nodes accumulates real registry and disk costs.</li>
  <li><strong>Distance from AI/ML relevance</strong>: Honestly, this tool is far from the training and inference workloads at the core of our platform. For organizations with no mobile testing demand, the direct value is limited. The value of this post lies not in “the emulator itself” but in “the operational patterns for device-passthrough containers.”</li>
  <li><strong>Security of privileged containers</strong>: <code class="language-plaintext highlighter-rouge">/dev/kvm</code> access and privileged settings complicate multi-tenant security boundaries. Preserving tenant isolation requires dedicated node pools and strict policies.</li>
</ul>

<p>docker-android is a powerful tool for mobile test automation and a useful reference for how to handle device-class workloads on Kubernetes. Even before the moment we need it directly, the operational patterns are worth understanding in advance.</p>

<hr />

<h2 id="sources">Sources</h2>

<ul>
  <li>docker-android (HQarroum): <a href="https://github.com/HQarroum/docker-android">https://github.com/HQarroum/docker-android</a></li>
  <li>Docker Hub image: <code class="language-plaintext highlighter-rouge">halimqarroum/docker-android</code></li>
  <li>scrcpy (remote screen control): <a href="https://github.com/Genymobile/scrcpy">https://github.com/Genymobile/scrcpy</a></li>
  <li>Original tweet (RT): <a href="https://x.com/hjguyhan/status/2069427245295493446">https://x.com/hjguyhan/status/2069427245295493446</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="dev" /><category term="docker" /><category term="android" /><category term="kubernetes" /><category term="kvm" /><category term="ci-cd" /><summary type="html"><![CDATA[docker-android packages an Android emulator into a single container and runs it headlessly. We verify image sizes and KVM requirements against the official documentation, and explore what running device-passthrough workloads looks like on the ThakiCloud Kubernetes platform.]]></summary></entry><entry xml:lang="en"><title type="html">Routing Claude Code to Your Own Models - Cost-Efficient Coding Infra with claude-code-router</title><link href="https://thakicloud.github.io/en/llmops/claude-code-router-onprem-routing/" rel="alternate" type="text/html" title="Routing Claude Code to Your Own Models - Cost-Efficient Coding Infra with claude-code-router" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/en/llmops/claude-code-router-onprem-routing</id><content type="html" xml:base="https://thakicloud.github.io/en/llmops/claude-code-router-onprem-routing/"><![CDATA[<pre><code class="language-mermaid">flowchart LR
    CC["Claude Code"] --&gt; CCR["claude-code-router proxy"]
    CCR --&gt;|default / background| GLM["Ollama Cloud · glm-5.2"]
    CCR --&gt;|think / longContext| MM["MiniMax-M2.7 (Anthropic endpoint)"]
    CCR -.-&gt;|coding subagent tag| KIMI["Ollama Cloud · kimi-k2.7-code"]
    CCR -.-&gt;|onprem option| VLLM["internal vLLM (GLM-air)"]
    AUDIT["daily cost-audit loop"] --&gt;|checks vs Sonnet| CCR
</code></pre>

<h2 id="overview">Overview</h2>

<p>Claude Code is a terminal-based agentic coding tool. By default it sends requests to the Anthropic API, but not every request carries the same weight. Background summaries, short completions, long-context analysis, and deep refactoring reasoning all demand different model tiers. Push everything to the most expensive model and cost piles up; push everything to the cheapest and quality collapses.</p>

<p><code class="language-plaintext highlighter-rouge">claude-code-router</code> (CCR) solves this with a routing layer. It sits as a proxy between Claude Code and the model backends and forks traffic by request type. This post is not just a concept tour. It is a record of calling three external models to verify behavior, fixing the problems found along the way (a dead API key, thinking-tag leakage), and finally attaching a loop that continuously measures whether the routing is actually cheaper than Anthropic Sonnet.</p>

<p>The governing principle, stated up front: <strong>every model routed through CCR is only worthwhile if it is more cost-efficient than Claude Sonnet.</strong> Otherwise you lower quality while the money still flows. So we don’t assert. We measure.</p>

<hr />

<h2 id="what-claude-code-router-is">What claude-code-router is</h2>

<p>CCR is a proxy that receives Anthropic-format requests, converts them to OpenAI-compatible (or other) formats, and forwards them to the configured provider. It does not modify the Claude Code client. Launch a session with <code class="language-plaintext highlighter-rouge">ccr code</code> and that session’s traffic routes through the <code class="language-plaintext highlighter-rouge">localhost:3456</code> proxy.</p>

<p>Key features:</p>

<ul>
  <li><strong>Per-request-type routing</strong>: <code class="language-plaintext highlighter-rouge">default</code>, <code class="language-plaintext highlighter-rouge">background</code>, <code class="language-plaintext highlighter-rouge">think</code>, <code class="language-plaintext highlighter-rouge">longContext</code>, <code class="language-plaintext highlighter-rouge">webSearch</code>, each mapped to a different model.</li>
  <li><strong>Multi-provider</strong>: any OpenAI-compatible endpoint can be registered. Here we use Ollama Cloud and MiniMax.</li>
  <li><strong>Transformers</strong>: a converter absorbs each provider’s API quirks. The <code class="language-plaintext highlighter-rouge">Anthropic</code> passthrough transformer for native Anthropic endpoints is the key tool in this post.</li>
  <li><strong>Dynamic switching</strong>: change models mid-session with <code class="language-plaintext highlighter-rouge">/model provider,model</code>.</li>
</ul>

<p>The verified CCR version is <code class="language-plaintext highlighter-rouge">1.0.62</code>. The config lives at <code class="language-plaintext highlighter-rouge">~/.claude-code-router/config.json</code>, centered on a <code class="language-plaintext highlighter-rouge">Providers</code> array and a <code class="language-plaintext highlighter-rouge">Router</code> object.</p>

<hr />

<h2 id="what-gets-routed---fixed-to-three-models">What gets routed - fixed to three models</h2>

<p>The model pool is exactly three. Adding more models complicates the routing table and inflates verification cost, so we deliberately narrowed it.</p>

<table>
  <thead>
    <tr>
      <th>Role</th>
      <th>Model</th>
      <th>Provider</th>
      <th>Note</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Primary (default/background)</td>
      <td><code class="language-plaintext highlighter-rouge">glm-5.2</code></td>
      <td>Ollama Cloud</td>
      <td>everyday coding, strong and cheap</td>
    </tr>
    <tr>
      <td>Reasoning (think/longContext)</td>
      <td><code class="language-plaintext highlighter-rouge">MiniMax-M2.7</code></td>
      <td>MiniMax</td>
      <td>thinking separated, very low per-token cost</td>
    </tr>
    <tr>
      <td>Coding subagent</td>
      <td><code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code></td>
      <td>Ollama Cloud</td>
      <td>hard coding turns only</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">glm-5.2</code> is the workhorse; only deep reasoning and long context go to MiniMax, and a tough coding turn goes to Kimi.</p>

<hr />

<h2 id="verification---we-called-we-didnt-assume">Verification - we called, we didn’t assume</h2>

<p>Before writing any config, we called all three models directly. To avoid inventing numbers we inspected real responses, and three facts surfaced.</p>

<p><strong>First, one Ollama Cloud key covers both GLM and Kimi.</strong> Both <code class="language-plaintext highlighter-rouge">glm-5.2</code> and <code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code> returned HTTP 200 from <code class="language-plaintext highlighter-rouge">https://ollama.com/v1</code>. Ollama Cloud bundles the GLM, Kimi, DeepSeek, and Qwen families behind a single key.</p>

<p><strong>Second, the standalone Kimi key was dead.</strong> The standalone Moonshot key in <code class="language-plaintext highlighter-rouge">.env</code> returned 401 (Invalid Authentication) against moonshot.ai, moonshot.cn, and the Anthropic-compatible endpoint alike. Fortunately Kimi K2 is reachable as Ollama Cloud’s <code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code>, so the dead key was not a dead end.</p>

<p><strong>Third, MiniMax’s endpoint choice decides quality.</strong> Called through the OpenAI-compatible endpoint (<code class="language-plaintext highlighter-rouge">/v1/chat/completions</code>), the model inlines its reasoning as <code class="language-plaintext highlighter-rouge">&lt;think&gt;...&lt;/think&gt;</code> tags in the body, and CCR’s conversion layer fails to strip them, so they leak to the user (musistudio/claude-code-router#964). Called through the native Anthropic endpoint (<code class="language-plaintext highlighter-rouge">/anthropic/v1/messages</code>), the same model returns clean <code class="language-plaintext highlighter-rouge">thinking</code> and <code class="language-plaintext highlighter-rouge">text</code> blocks.</p>

<p>That last item was a bug to fix, not a reason to drop MiniMax. The fix is in the config below.</p>

<hr />

<h2 id="configuration---secrets-out-of-the-repo-config-as-code">Configuration - secrets out of the repo, config as code</h2>

<p>Keys are not hardcoded into the config file. A generator script reads the repo’s <code class="language-plaintext highlighter-rouge">.env</code> and writes <code class="language-plaintext highlighter-rouge">~/.claude-code-router/config.json</code>. No keys remain in the repo, and rotating a key just means re-running the script.</p>

<p>The core generated config:</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"LOG"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
  </span><span class="nl">"HOST"</span><span class="p">:</span><span class="w"> </span><span class="s2">"127.0.0.1"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"PORT"</span><span class="p">:</span><span class="w"> </span><span class="mi">3456</span><span class="p">,</span><span class="w">
  </span><span class="nl">"API_TIMEOUT_MS"</span><span class="p">:</span><span class="w"> </span><span class="mi">1800000</span><span class="p">,</span><span class="w">
  </span><span class="nl">"Providers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://ollama.com/v1/chat/completions"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;OLLAMA_GLM_API_KEY&gt;"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"glm-5.2"</span><span class="p">,</span><span class="w"> </span><span class="s2">"kimi-k2.7-code"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"transformer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"use"</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="s2">"maxtoken"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"max_tokens"</span><span class="p">:</span><span class="w"> </span><span class="mi">16000</span><span class="w"> </span><span class="p">}]]</span><span class="w"> </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://api.minimax.io/anthropic/v1/messages"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;MINIMAX_API_KEY&gt;"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"MiniMax-M2.7"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"transformer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"use"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Anthropic"</span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">],</span><span class="w">
  </span><span class="nl">"Router"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"default"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"background"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"think"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax,MiniMax-M2.7"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"longContext"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax,MiniMax-M2.7"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"longContextThreshold"</span><span class="p">:</span><span class="w"> </span><span class="mi">60000</span><span class="p">,</span><span class="w">
    </span><span class="nl">"webSearch"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>The two lines in the MiniMax provider are what fix the thinking leak. Point <code class="language-plaintext highlighter-rouge">api_base_url</code> at the native Anthropic path and use the <code class="language-plaintext highlighter-rouge">Anthropic</code> passthrough transformer, and MiniMax responds in Anthropic message format (<code class="language-plaintext highlighter-rouge">thinking</code> + <code class="language-plaintext highlighter-rouge">text</code> blocks) from the start. Re-checked through the proxy, the response blocks were <code class="language-plaintext highlighter-rouge">["thinking", "text"]</code> with zero <code class="language-plaintext highlighter-rouge">&lt;think&gt;</code> leakage.</p>

<p>Reasoning models are slow to emit, so the timeout is generous (<code class="language-plaintext highlighter-rouge">1800000ms</code>), and <code class="language-plaintext highlighter-rouge">maxtoken</code> reserves output headroom so models like GLM and Kimi, which emit reasoning first, don’t burn the budget before the answer.</p>

<p>Subagents are routed not by config but by a prompt-leading tag. To delegate a hard coding task, prepend <code class="language-plaintext highlighter-rouge">&lt;CCR-SUBAGENT-MODEL&gt;ollama,kimi-k2.7-code&lt;/CCR-SUBAGENT-MODEL&gt;</code> to the prompt.</p>

<hr />

<h2 id="where-and-how-to-connect">Where and how to connect</h2>

<p>There is a single connection point. Start a session with <code class="language-plaintext highlighter-rouge">ccr code</code> in your working repo, and that session’s main and subagent traffic all route through the proxy per the table above. Native <code class="language-plaintext highlighter-rouge">claude</code> still connects directly to Anthropic, so it is unaffected.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># generate config, then start the router</span>
python3 scripts/ccr/gen_ccr_config.py <span class="o">&amp;&amp;</span> ccr restart

<span class="c"># start the cost-routed session (this is the connection point)</span>
ccr code

<span class="c"># switch models per task inside the session</span>
/model ollama,kimi-k2.7-code     <span class="c"># hard coding turn</span>
/model minimax,MiniMax-M2.7      <span class="c"># deep reasoning turn</span>
/model ollama,glm-5.2            <span class="c"># everyday coding</span>
</code></pre></div></div>

<p>For cost efficiency, the recommended pattern is hybrid. Run bulk, repetitive, AFK-style work (test generation, mass refactors, log analysis, translation, code exploration) under <code class="language-plaintext highlighter-rouge">ccr code</code> to cut cost, and keep judgment-heavy work (architecture decisions, subtle debugging) on the native <code class="language-plaintext highlighter-rouge">claude</code> subscription session. Moving everything to the routed session makes GLM your main loop, which can drop quality on hard tasks.</p>

<hr />

<h2 id="cost-efficiency---measured-against-sonnet-continuously">Cost efficiency - measured against Sonnet, continuously</h2>

<p>The reason this setup exists is cost. So instead of claiming “it’s cheaper,” we measure.</p>

<p>Rates verified on 2026-06-24 (USD per 1M tokens):</p>

<table>
  <thead>
    <tr>
      <th>Model</th>
      <th>Input</th>
      <th>Output</th>
      <th>Billing</th>
      <th>vs Sonnet</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Claude Sonnet 4.6 (baseline)</td>
      <td>$3.00</td>
      <td>$15.00</td>
      <td>per-token</td>
      <td>1.0x</td>
    </tr>
    <tr>
      <td>MiniMax-M2.7</td>
      <td>$0.24</td>
      <td>$0.96</td>
      <td>per-token</td>
      <td>~0.07x</td>
    </tr>
    <tr>
      <td>glm-5.2 / kimi-k2.7-code</td>
      <td>—</td>
      <td>—</td>
      <td>subscription $20/mo (Pro)</td>
      <td>usage-dependent</td>
    </tr>
  </tbody>
</table>

<p>MiniMax-M2.7 is about 7-8% of Sonnet’s per-token rate, so it is always dramatically cheaper. Ollama Cloud, by contrast, is a flat monthly subscription rather than per-token. Its effective rate is <code class="language-plaintext highlighter-rouge">monthly fee / monthly tokens used</code>, and at low volume the $20 flat fee is actually a loss. Using a blended $9/M, you must push <strong>roughly 2.2M tokens per month</strong> before it beats Sonnet.</p>

<p>That break-even is a measurement target, not a guess. CCR logs record the routed model and input/output tokens per request. A measurement script aggregates these, computing the ratio of actual cost to Sonnet-equivalent cost for per-token models, and projected-monthly Sonnet cost versus the subscription fee for subscription models. Results accumulate in a history file to track the trend, where improvement means the ratio falling over time.</p>

<p>The loop runs once a day via launchd. Claude is not in the loop; only a plain script runs on cron, so the measurement itself costs nothing. If a per-token model is ever found to be more expensive than Sonnet, a Slack alert fires. A subscription model below break-even (under-utilized) is reported but not alerted, to avoid noise during ramp-up.</p>

<p>The action rules are tied to the measurement. If a per-token model’s ratio is 1.0 or higher (more expensive than Sonnet), it comes off the routing immediately. If a subscription model stays under-utilized for months, downgrade the plan or move that route to a cheap per-token model. When prices change, updating the pricing-table file is enough to reflect it in the next run.</p>

<hr />

<h2 id="thakicloud-platform-perspective">ThakiCloud platform perspective</h2>

<p>This routing model fits naturally with the infrastructure ThakiCloud already runs.</p>

<p><strong>Code security.</strong> In environments where source code cannot leave the building (finance, public sector, healthcare), you only need to switch <code class="language-plaintext highlighter-rouge">default</code> in the config above to an internal vLLM endpoint. You keep Claude Code’s usability while prompts and code never leave. The external-model setup here is for cost verification; drop in-house GPU serving into the same skeleton and you have the on-premise version.</p>

<p><strong>Cost control.</strong> Per-task routing is per-cost routing. Send high-frequency, low-difficulty requests to cheap models and reserve top-tier models for hard reasoning, and you narrow expensive usage to where it’s truly needed, with the measurement loop proving the effect in numbers.</p>

<p><strong>Policy as code.</strong> Providers, routing rules, the pricing table, and the measurement criteria are all managed as text files committed to the repo. Only keys live in <code class="language-plaintext highlighter-rouge">.env</code> and the config is reproduced by a generator, so the same setup restores on any machine.</p>

<hr />

<h2 id="limits-and-counterarguments">Limits and counterarguments</h2>

<p>A router does not solve everything. Several points deserve a cold look.</p>

<ul>
  <li><strong>Quality gap</strong>: routing value depends on backend model quality. Open models do not always match top closed models on complex multi-step refactors or subtle debugging. Hence the hybrid recommendation.</li>
  <li><strong>Tool-call reliability</strong>: Claude Code leans heavily on tool calls. The OpenAI-compatible conversion layer can wobble tool-call formats, so it is safe for exploration/summary subagents but warrants gradual rollout for edit/implementation subagents.</li>
  <li><strong>Subscription trap</strong>: Ollama Cloud is flat-rate, so low usage is a loss. Below break-even, Sonnet is simply cheaper. The measurement loop watches exactly this point.</li>
  <li><strong>Proxy is a single point of failure</strong>: main traffic also passes through CCR, so if the proxy dies the session stalls. The fallback is native <code class="language-plaintext highlighter-rouge">claude</code>.</li>
  <li><strong>The “free” framing trap</strong>: some forks tout removing telemetry or safety guards as “free.” That is a direction a company cannot endorse. The value we take is not free but control - we decide which request goes to which model, and we measure the cost.</li>
</ul>

<p>CCR is not a cost-cutting magic trick but a routing control device. Combined with a verified model pool, fixes for real bugs like thinking leakage, and continuous measurement against Sonnet, it becomes a meaningful gain on both security and cost.</p>

<hr />

<h2 id="sources">Sources</h2>

<ul>
  <li>claude-code-router (musistudio): <a href="https://github.com/musistudio/claude-code-router">https://github.com/musistudio/claude-code-router</a></li>
  <li>MiniMax thinking-leak issue: <a href="https://github.com/musistudio/claude-code-router/issues/964">claude-code-router#964</a></li>
  <li>MiniMax M2.7 pricing: <a href="https://openrouter.ai/minimax/minimax-m2.7">openrouter.ai/minimax/minimax-m2.7</a></li>
  <li>Ollama Cloud pricing: <a href="https://ollama.com/pricing">ollama.com/pricing</a></li>
  <li>Claude API pricing: <a href="https://platform.claude.com/docs/en/about-claude/pricing">platform.claude.com/docs pricing</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="llmops" /><category term="claude-code" /><category term="model-routing" /><category term="cost-optimization" /><category term="ollama" /><category term="minimax" /><category term="on-premise" /><summary type="html"><![CDATA[Routing Claude Code traffic across glm-5.2, MiniMax-M2.7, and Kimi K2 with claude-code-router. A hands-on record of verifying all three models live, fixing MiniMax thinking leakage, and building a loop that continuously checks every routed model is cheaper than Sonnet.]]></summary></entry><entry xml:lang="en"><title type="html">Connecting Claude Code to Self-Hosted Models with free-claude-code: A Real-World Test of a 17-Provider Routing Proxy</title><link href="https://thakicloud.github.io/en/llmops/free-claude-code-router/" rel="alternate" type="text/html" title="Connecting Claude Code to Self-Hosted Models with free-claude-code: A Real-World Test of a 17-Provider Routing Proxy" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/en/llmops/free-claude-code-router</id><content type="html" xml:base="https://thakicloud.github.io/en/llmops/free-claude-code-router/"><![CDATA[<h2 id="overview">Overview</h2>

<p>Claude Code is a powerful coding agent. However, because every request goes directly to the Anthropic API, it creates a constraint for organizations that need to control costs or keep data within their own boundaries. The recently trending <code class="language-plaintext highlighter-rouge">free-claude-code</code> project addresses this exact point. It is a proxy layer that intercepts Claude Code traffic and routes it to 17 different providers. It is an MIT-licensed project with 36.7k GitHub stars, 5.7k forks, and 712 commits.</p>

<p>The project’s marketing tagline is “Claude Code forever free.” The approach routes traffic to free or low-cost tier providers, and this framing is frankly overstated in some respects and sits in a gray area from a Terms of Service perspective. This article therefore focuses not on the “free” angle, but on what this tool means for organizations like ThakiCloud that <strong>serve their own models on Kubernetes and want to connect Claude Code to their own infrastructure</strong>. The key points are that code and prompts never leave the tenancy boundary, per-token cloud billing disappears, and no client-side modifications are needed because the endpoint is Anthropic-compatible.</p>

<blockquote>
  <p>Note: A previous article, “Routing Claude Code to In-House Models - claude-code-router,” focused on <strong>cost arbitrage</strong> between cloud models (glm, MiniMax, Kimi). This article is about a different tool (<code class="language-plaintext highlighter-rouge">free-claude-code</code>), covering the connection to <strong>self-hosted backends (Ollama, vLLM)</strong> — not cloud models — and the deployment risks that surfaced in the process.</p>
</blockquote>

<h2 id="what-this-tool-does">What This Tool Does</h2>

<p><code class="language-plaintext highlighter-rouge">free-claude-code</code> is a local proxy server that receives requests sent by Claude Code (and Codex). Its core feature is that it <strong>exactly mimics an Anthropic-compatible endpoint</strong>. From the client’s perspective, it is indistinguishable from the real Anthropic API, so the backend can be swapped without changing a single line of Claude Code.</p>

<p>The server is written in FastAPI and exposes the following endpoints:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">/v1/messages</code> - Anthropic Messages API compatible (the primary path for Claude Code)</li>
  <li><code class="language-plaintext highlighter-rouge">/v1/models</code> - Model listing</li>
  <li><code class="language-plaintext highlighter-rouge">/v1/responses</code> - OpenAI Responses API compatible (for Codex; internally converted to Messages)</li>
</ul>

<p>When a request arrives, a <strong>model router</strong> decides which provider to send it to, and a <strong>normalizer</strong> transforms thinking blocks, tool_calls, and error responses into the shape each client expects. Because response formats differ across providers, this normalization layer is where the real complexity lies.</p>

<p>To elaborate on why normalization is difficult: Claude Code assumes Anthropic’s own response structure. For instance, reasoning steps arrive as <code class="language-plaintext highlighter-rouge">thinking</code> blocks and tool calls as <code class="language-plaintext highlighter-rouge">tool_use</code> content blocks. DeepSeek, however, exports reasoning as a separate field, and OpenAI-compatible providers return tool calls as a <code class="language-plaintext highlighter-rouge">tool_calls</code> array. Even though they all mean “a tool was called,” the wire format differs in each case. The normalizer must absorb these differences and ensure Claude Code receives identically shaped responses regardless of which backend is used. The Codex path (<code class="language-plaintext highlighter-rouge">/v1/responses</code>) goes one step further, converting OpenAI Responses requests internally to Anthropic Messages before sharing the same router, normalizer, and provider adapters. This means protocol conversion happens in both directions — the key distinction between a simple reverse proxy and a routing proxy.</p>

<p><img src="/assets/images/free-claude-code-router-diagram.png" alt="free-claude-code routing architecture" />
<em>Figure 1. The FastAPI proxy receives Anthropic-compatible traffic from Claude Code and routes it to 17 providers. From ThakiCloud’s perspective, the important paths are the self-hosted backends on the right (Ollama, LM Studio, vLLM).</em></p>

<p>The supported providers number 17. On the cloud side: NVIDIA NIM, OpenRouter, Google AI Studio (Gemini), DeepSeek, Mistral La Plateforme, Mistral Codestral, OpenCode Zen, OpenCode Go, Wafer, Kimi, Cerebras, Groq, Fireworks, and Z.ai. On the <strong>self-hosted side: LM Studio, llama.cpp, and Ollama</strong>. The last three are the meaningful ones from ThakiCloud’s perspective. Since Ollama and llama.cpp expose OpenAI-compatible endpoints, a vLLM server deployed the same way on Kubernetes can be attached identically.</p>

<p>Tier-based routing is controlled via environment variables. <code class="language-plaintext highlighter-rouge">MODEL_OPUS</code>, <code class="language-plaintext highlighter-rouge">MODEL_SONNET</code>, and <code class="language-plaintext highlighter-rouge">MODEL_HAIKU</code> each specify which model to route to for the three Claude tiers; if unspecified, the fallback <code class="language-plaintext highlighter-rouge">MODEL</code> is used. This enables differentiated placement — for example, routing lightweight Haiku traffic to a small local model and heavier Opus traffic to a larger one.</p>

<h2 id="installation-and-integration">Installation and Integration</h2>

<p>The official installation path is a shell one-liner:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># macOS / Linux</span>
curl <span class="nt">-fsSL</span> <span class="s2">"https://github.com/Alishahryar1/free-claude-code/blob/main/scripts/install.sh?raw=1"</span> | sh

<span class="c"># Windows PowerShell</span>
irm <span class="s2">"https://github.com/Alishahryar1/free-claude-code/blob/main/scripts/install.ps1?raw=1"</span> | iex
</code></pre></div></div>

<p>Rather than the shell one-liner, I verified the package by installing it directly in an isolated sandbox, in order not to contaminate ThakiCloud’s shared virtual environment per our Python runtime rules.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># Isolated worktree + ephemeral venv (shared .venv is 3.12.8 and would conflict)</span>
uv venv <span class="nt">--python</span> 3.14 .expenv
<span class="nv">VIRTUAL_ENV</span><span class="o">=</span>.expenv uv pip <span class="nb">install</span> <span class="s2">"git+https://github.com/Alishahryar1/free-claude-code.git"</span>
</code></pre></div></div>

<p>The package itself installs cleanly. Dependencies such as fastapi, uvicorn, httpx, pydantic, openai, and loguru resolve successfully, and console scripts like <code class="language-plaintext highlighter-rouge">fcc-server</code>, <code class="language-plaintext highlighter-rouge">fcc-init</code>, and <code class="language-plaintext highlighter-rouge">fcc-claude</code> are created. After starting the server, Claude Code is directed to the proxy as follows:</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fcc-server            <span class="c"># Start the FastAPI proxy (default http://127.0.0.1:8082)</span>
<span class="c"># Self-hosted backend example (Ollama):</span>
<span class="c">#   MODEL_HAIKU=ollama/llama3.2:3b</span>
<span class="c">#   MODEL_SONNET=ollama/qwen2.5:7b</span>
<span class="c"># Specify the base URL to point Claude Code at the proxy, then use as normal</span>
</code></pre></div></div>

<p>The admin UI is at <code class="language-plaintext highlighter-rouge">http://127.0.0.1:8082/admin</code> and is only accessible from loopback. Provider keys, model routing, and messaging and voice settings are managed here.</p>

<h2 id="actual-experiment-results">Actual Experiment Results</h2>

<p>During validation I encountered <strong>a point where reproduction was blocked</strong>, and I record it as-is. Not fabricating numbers is a principle of this report.</p>

<h3 id="boot-blocker-hard-python-314-requirement">Boot Blocker: Hard Python 3.14 Requirement</h3>

<p><code class="language-plaintext highlighter-rouge">free-claude-code</code> v2.3.14 has hardcoded <code class="language-plaintext highlighter-rouge">requires-python = "&gt;=3.14.0"</code>. Python 3.14 is the latest version, only officially released in October 2025. The problem was that the only available 3.14 in the test environment was an alpha build (3.14.0a7). Running <code class="language-plaintext highlighter-rouge">fcc-server</code> on this alpha fails with the following error:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ImportError: cannot import name 'get_annotate_from_class_namespace'
from 'annotationlib'
</code></pre></div></div>

<p>This is a conflict where the pinned pydantic expects the <code class="language-plaintext highlighter-rouge">annotationlib</code> API of the final 3.14, but that symbol is not yet present in the early alpha. I then attempted to force-run it under the next lower stable version (3.13), but installation itself is rejected because of the hard requirement in the package metadata:</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>free-claude-code==2.3.14 cannot be used ... your requirements are unsatisfiable.
</code></pre></div></div>

<p>The conclusion is clear: <strong>in environments without a stable Python 3.14, this proxy will not boot.</strong> Reproduction attempt failed: the package hard-requires freshly released Python 3.14, but the only available 3.14 is an alpha that conflicts with the pinned pydantic. This is less a defect in the tool than a problem of <strong>aggressive version pinning</strong> that is at odds with the reality that production images typically remain on 3.11–3.12.</p>

<h3 id="direct-measurement-of-the-self-hosted-routing-path">Direct Measurement of the Self-Hosted Routing Path</h3>

<p>Although the proxy itself was blocked at boot, the <strong>mechanism</strong> this tool uses to call the <code class="language-plaintext highlighter-rouge">ollama</code> provider is the OpenAI-compatible endpoint. I therefore measured this path by calling local Ollama directly. These are the backend’s own routing performance numbers without the proxy overhead that fcc would add. The results of mapping Claude’s three tiers to local models are as follows (Apple Silicon, identical prompt, 64-token cap):</p>

<p><img src="/assets/images/free-claude-code-router-results.png" alt="Self-hosted routing measurement results" />
<em>Figure 2. Latency and throughput when routing Claude tiers to local Ollama models. qwen3:8b placed on the opus path is a thinking model that outputs extended reasoning tokens, significantly increasing the time.</em></p>

<table>
  <thead>
    <tr>
      <th>Routing</th>
      <th>Model</th>
      <th>Latency</th>
      <th>Completion Tokens</th>
      <th>Throughput</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>haiku</td>
      <td>llama3.2:3b</td>
      <td>0.49s</td>
      <td>33</td>
      <td>67.3 tok/s</td>
    </tr>
    <tr>
      <td>sonnet</td>
      <td>qwen2.5:7b</td>
      <td>0.56s</td>
      <td>20</td>
      <td>35.7 tok/s</td>
    </tr>
    <tr>
      <td>opus</td>
      <td>qwen3:8b</td>
      <td>8.12s</td>
      <td>281</td>
      <td>34.6 tok/s</td>
    </tr>
  </tbody>
</table>

<p>The small model (llama3.2:3b) finishes responding in under 0.5 seconds — fast enough for Haiku replacement traffic. qwen2.5:7b at 0.56 seconds is also practical. The qwen3:8b placed on the opus path, however, took 8.12 seconds, because the thinking model first emits 281 reasoning tokens. The throughput itself (34.6 tok/s) is normal, but this measurement confirms that <strong>placing a reasoning model in a heavy tier causes a token explosion and significantly increases perceived latency</strong>. A practical lesson: when designing tier mappings, the reasoning-token behavior of the model must also be considered.</p>

<h2 id="application-and-implications-for-thakiclouds-k8s-aiml-saas-platform">Application and Implications for ThakiCloud’s K8s AI/ML SaaS Platform</h2>

<p>The real value of this tool lies not in “free” but in the <strong>connection pattern</strong>. Once an Anthropic-compatible proxy is inserted as a layer, commercial agents like Claude Code can be attached directly to our infrastructure.</p>

<p>ThakiCloud schedules GPUs with Kueue and serves models with vLLM on Kubernetes. Since vLLM provides an OpenAI-compatible endpoint (<code class="language-plaintext highlighter-rouge">/v1/chat/completions</code>), it can be connected to <code class="language-plaintext highlighter-rouge">free-claude-code</code>’s self-hosted provider path in the same way as Ollama or llama.cpp. The connection method is common across self-hosted providers: specify the base URL as the cluster’s vLLM service endpoint and add the provider prefix to the model identifier. Just as Ollama uses <code class="language-plaintext highlighter-rouge">ollama/llama3.2:3b</code>, an in-house model served on vLLM is added to the routing targets with the same prefix convention. This enables the following:</p>

<ul>
  <li><strong>Data sovereignty</strong>: Code and prompts never leave the tenancy boundary. This is essential in regulated environments such as on-premises deployment and NIS (National Intelligence Service) compliance requirements.</li>
  <li><strong>Cost structure shift</strong>: Per-token metered billing is replaced by fixed GPU costs. The higher the usage, the faster self-serving reaches its break-even point.</li>
  <li><strong>Tiered differentiated placement</strong>: Lightweight Haiku traffic can be routed to small models, and heavier workloads to larger ones, optimizing GPU occupancy. The measurements above provide baseline numbers for this differentiated placement.</li>
</ul>

<p>That said, rather than adopting this tool as-is, it is more rational to <strong>borrow only the validated routing pattern</strong>. In a multi-tenant environment, the proxy must have per-tenant authentication, isolation, and observability, but <code class="language-plaintext highlighter-rouge">free-claude-code</code>’s admin UI assumes a single loopback user and is insufficient as-is. The idea behind the Anthropic-compatible normalization layer is worth borrowing, but authentication, quotas, and logging must be re-implemented to match our gateway standards.</p>

<h2 id="limitations-and-counterarguments">Limitations and Counterarguments</h2>

<p>First, there is the <strong>Terms of Service gray area</strong>. The “Claude Code for free” framing relies on routing through free-tier providers, which may conflict with each service’s terms. In enterprise environments, legitimate and sustainable use is strictly <strong>routing to owned backends (self-served models)</strong>. This is why this article emphasizes only the self-hosting path.</p>

<p>Second, there is <strong>aggressive version pinning</strong>. As seen above, the hard Python 3.14 requirement immediately prevents booting in environments without a stable runtime. Considering the cost and risk of upgrading production container images to 3.14, inserting this tool directly into a deployment pipeline at this point carries too much friction.</p>

<p>Third, <strong>quality equivalence is not guaranteed</strong>. Replacing Claude’s Opus or Sonnet with different models does not preserve coding quality. Routing is a trade-off that gains cost savings and data sovereignty at the expense of response quality; which traffic to send where must be determined by measurement, depending on task difficulty.</p>

<p>Fourth, the measurements in this report are <strong>direct backend call numbers without going through the proxy</strong>. The normalization and routing overhead of fcc is not included. Once a stable Python 3.14 environment is secured, I plan to re-measure the round-trip latency through the proxy and supplement these results.</p>

<p>In summary, <code class="language-plaintext highlighter-rouge">free-claude-code</code> is risky if consumed as a “free hack,” but read as an <strong>open-source reference for Anthropic-compatible routing patterns</strong>, it is a solid starting point for the design of connecting commercial agents to self-hosted inference infrastructure.</p>

<h2 id="sources">Sources</h2>

<ul>
  <li>GitHub: <a href="https://github.com/Alishahryar1/free-claude-code">Alishahryar1/free-claude-code</a> (MIT, 36.7k stars, v2.3.14)</li>
  <li>Measurement data: Direct calls to local Ollama OpenAI-compatible endpoint (llama3.2:3b, qwen2.5:7b, qwen3:8b, Apple Silicon)</li>
  <li>Related article: ThakiCloud Tech Blog “Routing Claude Code to In-House Models - claude-code-router”</li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="llmops" /><category term="free-claude-code" /><category term="Claude Code" /><category term="LLM Gateway" /><category term="Model Routing" /><category term="Ollama" /><category term="vLLM" /><category term="Self-Hosting" /><category term="FastAPI" /><category term="LLM Ops" /><summary type="html"><![CDATA[free-claude-code (36.7k stars) intercepts Claude Code traffic through an Anthropic-compatible FastAPI proxy and routes it to 17 providers. This report documents direct routing to a local Ollama backend with latency measurements, and honestly records the deployment risk introduced by a hard Python 3.14 requirement.]]></summary></entry><entry xml:lang="en"><title type="html">The Complete Gemma 4 Lineup: Five Apache 2.0 Open-Weight Models and an On-Premises Serving Guide</title><link href="https://thakicloud.github.io/en/owm/gemma-4-open-weight-lineup/" rel="alternate" type="text/html" title="The Complete Gemma 4 Lineup: Five Apache 2.0 Open-Weight Models and an On-Premises Serving Guide" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/en/owm/gemma-4-open-weight-lineup</id><content type="html" xml:base="https://thakicloud.github.io/en/owm/gemma-4-open-weight-lineup/"><![CDATA[<p>⏱️ <strong>Estimated reading time</strong>: 10 min</p>

<p><img src="/assets/images/gemma-4-open-weight-lineup-hero.png" alt="Gemma 4 lineup concept" /></p>

<h2 id="gemma-4-overview">Gemma 4 Overview</h2>

<p>Released by Google DeepMind on April 2, 2026, Gemma 4 is the most intelligent open-weight model family Gemma has shipped to date. Google states that it was built on the same research and technology that underpins Gemini 3. In other words, think of it as the training recipe behind a closed flagship distilled down into an open-weight lineup.</p>

<p>From a ThakiCloud perspective, two changes stand out this generation. First, the license moved to <strong>Apache 2.0</strong>. Unlike earlier Gemma generations that carried a separate Gemma usage policy, Gemma 4 adopts a commercially permissive standard open-source license. Second, it ships not as a single size but as a five-model lineup that spans <strong>everything from the edge (phones) to a single server GPU</strong>. That means you can pick a deployment target by device tier within the same model family.</p>

<p>Rather than going deep on a single model, this post aims to <strong>compare all five models at a glance and clarify which one to choose for which situation</strong>.</p>

<h2 id="the-gemma-4-lineup-all-five-models">The Gemma 4 Lineup: All Five Models</h2>

<p>Gemma 4 consists of the following five models. Organized by parameters, context, modality, and architecture per the model card:</p>

<table>
  <thead>
    <tr>
      <th>Model</th>
      <th>Parameters</th>
      <th>Context</th>
      <th>Input Modalities</th>
      <th>Architecture</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>E2B</strong></td>
      <td>2.3B effective (5.1B with embeddings)</td>
      <td>128K</td>
      <td>Text + Image + Audio</td>
      <td>Dense</td>
    </tr>
    <tr>
      <td><strong>E4B</strong></td>
      <td>4.5B effective (8B with embeddings)</td>
      <td>128K</td>
      <td>Text + Image + Audio</td>
      <td>Dense</td>
    </tr>
    <tr>
      <td><strong>12B Unified</strong></td>
      <td>11.95B</td>
      <td>256K</td>
      <td>Text + Image + Audio</td>
      <td>Dense</td>
    </tr>
    <tr>
      <td><strong>26B A4B</strong></td>
      <td>25.2B total / 3.8B active</td>
      <td>256K</td>
      <td>Text + Image</td>
      <td>MoE (8 of 128 experts active)</td>
    </tr>
    <tr>
      <td><strong>31B Dense</strong></td>
      <td>30.7B</td>
      <td>256K</td>
      <td>Text + Image</td>
      <td>Dense</td>
    </tr>
  </tbody>
</table>

<p>All five output text. Audio input is supported only on the E2B, E4B, and 12B models; the 26B and 31B handle text and image.</p>

<p>The “E” in <code class="language-plaintext highlighter-rouge">E2B</code> and <code class="language-plaintext highlighter-rouge">E4B</code> stands for effective parameters. It is the size based on actual compute parameters excluding the embedding table, and effective values are the more realistic figure when gauging memory and compute budgets. Both models squarely target edge devices such as phones and laptops.</p>

<p>The heart of the lineup is the <strong>division of labor between the two top models: the 26B A4B (MoE) and the 31B (Dense)</strong>.</p>

<ul>
  <li><strong>26B A4B</strong> is a Mixture-of-Experts. It holds 25.2B total parameters but activates only about 3.8B per token. The full weights still have to sit in VRAM, but per-token compute (FLOPs) is based on the active parameters, which is <strong>favorable for latency and throughput</strong>. It suits serving where you need to push large volumes of requests quickly.</li>
  <li><strong>31B Dense</strong> is a standard dense model where every parameter participates on every token. Oriented toward maximizing quality and fine-tuning suitability, Google positions the 31B as the quality ceiling of the lineup.</li>
</ul>

<p>According to Google, the 31B ranked #3 among open models worldwide on the Arena AI text leaderboard and the 26B placed #6, and it described the lineup as “competing with models 20x its size.” Such leaderboard rankings shift over time, so it is better to read them as a direction (“high intelligence density relative to its class”) than as absolute figures.</p>

<h3 id="model-selection-flow">Model Selection Flow</h3>

<pre><code class="language-mermaid">flowchart TD
    A[Choose a Gemma 4 model] --&gt; B{Deployment target?}
    B --&gt;|Phone/edge device| C[E2B / E4B&lt;br/&gt;128K, audio support]
    B --&gt;|Single-GPU on-prem| D{Priority?}
    D --&gt;|Throughput/latency| E[26B A4B MoE&lt;br/&gt;active 3.8B]
    D --&gt;|Top quality/fine-tuning| F[31B Dense]
    D --&gt;|Multimodal + audio + balance| G[12B Unified&lt;br/&gt;256K, audio support]
</code></pre>

<h2 id="architecture-hybrid-attention-and-multimodality">Architecture: Hybrid Attention and Multimodality</h2>

<p>All five Gemma 4 models share a <strong>hybrid attention</strong> mechanism. It interleaves local sliding-window attention with full global attention. Short ranges are handled cheaply by the sliding window, while global attention is periodically inserted to capture full-context dependencies, with the goal of curbing memory and compute cost on long contexts. This design is the backdrop to the upper models (12B/26B/31B) handling a 256K context.</p>

<p>Multimodality is the default this generation. All five take text and image as input, and the edge/mid tiers (E2B/E4B/12B) also handle audio input. Features aimed at agentic workflows are built in too. Function calling, structured JSON output, and native system instructions are officially supported, and the lineup emphasizes improvements in multi-step planning and logical reasoning over the previous generation. The training data cutoff is January 2025.</p>

<p>Language support is broad: 35+ languages out of the box and 140+ languages at the pretraining level. Actual quality in Korean operation requires direct evaluation, but the multilingual coverage itself is wide.</p>

<h2 id="benchmarks">Benchmarks</h2>

<p>The representative benchmarks Google published for the 31B instruction-tuned model are below, per the model card.</p>

<table>
  <thead>
    <tr>
      <th>Benchmark</th>
      <th>31B (IT)</th>
      <th>Area Measured</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>MMLU-Pro</td>
      <td>85.2%</td>
      <td>General knowledge &amp; reasoning</td>
    </tr>
    <tr>
      <td>GPQA Diamond</td>
      <td>84.3%</td>
      <td>Graduate-level science reasoning</td>
    </tr>
    <tr>
      <td>LiveCodeBench v6</td>
      <td>80.0%</td>
      <td>Code generation</td>
    </tr>
    <tr>
      <td>MATH-Vision</td>
      <td>85.6%</td>
      <td>Vision-grounded math</td>
    </tr>
    <tr>
      <td>Codeforces (ELO)</td>
      <td>2150</td>
      <td>Competitive programming</td>
    </tr>
  </tbody>
</table>

<p>At the 31B single-node scale, GPQA Diamond at 84.3% and MMLU-Pro at 85.2% are top-tier among comparable open-weight models. That said, the benchmarks are for the instruction-tuned variant, and real domain-task performance must be validated separately. In particular, Korean reasoning and coding tasks are not directly reflected in public benchmarks, so measuring them with an internal eval set is recommended.</p>

<h2 id="serving-and-deployment">Serving and Deployment</h2>

<p>Gemma 4 secured broad serving-ecosystem support from launch. The official paths are:</p>

<ul>
  <li><strong>Inference servers</strong>: vLLM, SGLang, llama.cpp, Ollama, LM Studio, NVIDIA NIM</li>
  <li><strong>Frameworks</strong>: Hugging Face Transformers / TRL / Transformers.js / Candle, Keras, MaxText, NeMo</li>
  <li><strong>Edge/on-device</strong>: LiteRT-LM, Cactus</li>
  <li><strong>Fine-tuning/quantization</strong>: Unsloth, Tunix</li>
  <li><strong>Deployment infra</strong>: Docker, Baseten, Google Cloud (Vertex AI)</li>
</ul>

<p>Weights can be downloaded from the <a href="https://huggingface.co/collections/google/gemma-4">google/gemma-4 collection on Hugging Face</a>, Kaggle, and Ollama.</p>

<h3 id="on-prem-gpu-requirements-estimated">On-Prem GPU Requirements (Estimated)</h3>

<p>A rough on-prem deployment guide based on each model’s BF16 weight memory. These are weight estimates excluding KV cache and runtime overhead, so leave headroom for your context length and concurrent request count in an actual deployment.</p>

<table>
  <thead>
    <tr>
      <th>Model</th>
      <th>BF16 weights (est.)</th>
      <th>Realistic on-prem starting point</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>E2B / E4B</td>
      <td>~5–16GB [est.]</td>
      <td>Consumer GPU, laptop, phone (LiteRT)</td>
    </tr>
    <tr>
      <td>12B Unified</td>
      <td>~24GB [est.]</td>
      <td>Single 24GB GPU (RTX 4090/L4 class), headroom when quantized</td>
    </tr>
    <tr>
      <td>26B A4B (MoE)</td>
      <td>~50GB [est.]</td>
      <td>A single H100/A100 80GB</td>
    </tr>
    <tr>
      <td>31B Dense</td>
      <td>~62GB [est.]</td>
      <td>A single H100/A100 80GB</td>
    </tr>
  </tbody>
</table>

<p>The practical strength of the lineup is that both top models (26B, 31B) fit on <strong>a single 80GB GPU</strong> in BF16. That means you can run frontier-grade inference on a single server without multi-node tensor parallelism, which sharply lowers the bar to on-prem adoption. With a smaller GPU budget, step down to the 12B or to a quantized path (GGUF Q4/Q8). Thanks to its MoE nature computing only the active 3.8B, the 26B has a throughput edge per token over the 31B Dense at the same VRAM.</p>

<h2 id="implications-for-the-thakicloud-k8s-aiml-saas-platform">Implications for the ThakiCloud K8s AI/ML SaaS Platform</h2>

<p>The Gemma 4 lineup meshes well with ThakiCloud’s multi-tenant serving strategy. It matters on three fronts.</p>

<p><strong>Apache 2.0 unlocks the adoption barrier.</strong> A frontier-grade open-weight family released under standard Apache 2.0 is highly significant for enterprise and on-prem adoption. You can embed it in commercial services without the burden of reviewing a separate usage policy and freely distribute fine-tuned artifacts. It is a model family you can propose directly to environments with strict license compliance, such as domestic public-sector and finance, and to on-prem customers who require self-hosting.</p>

<p><strong>The lineup itself aligns with multi-tenant GPU routing.</strong> ThakiCloud manages GPU quotas with Kueue and serves models with vLLM. Gemma 4’s five-model lineup is a structure that lets you route model tiers within one family to match tenant needs (latency-sensitive, quality-first, edge inference). Route light chat/summarization to the 12B, throughput-critical batches to the 26B MoE, and high-difficulty reasoning/coding to the 31B, and you can optimize the GPU budget by task tier while keeping the same tokenizer and prompt format.</p>

<p><strong>Single-80GB-GPU serving simplifies the cost model.</strong> That the 26B and 31B fit on a single H100/A100 simplifies Kueue GPU job cost estimation. The communication overhead and scheduling complexity of multi-node tensor parallelism disappear, so you can price cleanly with a per-tenant dedicated-single-GPU model. The 26B MoE’s active-3.8B trait means it can take more concurrent requests on the same GPU, which is also favorable on a per-request unit-cost basis.</p>

<p>In short, Gemma 4 is a fit as a reference model family when ThakiCloud proposes a “single-GPU on-prem + multi-tenant model routing” operating pattern to customers.</p>

<h2 id="limitations-and-counterpoints">Limitations and Counterpoints</h2>

<p>For balance, a few caveats deserve mention.</p>

<ul>
  <li><strong>The gap between benchmarks and real use.</strong> The published figures center on the instruction-tuned, English-language benchmarks. Korean domain tasks, especially RAG and agent tool-call accuracy, must be re-measured with your own eval set.</li>
  <li><strong>The operational difficulty of MoE serving.</strong> The 26B A4B has low per-token compute but must keep the full weights resident in VRAM, and expert routing affects batch efficiency and memory patterns. The simplistic reading “it’s small because active is 3.8B” is risky.</li>
  <li><strong>Asymmetric audio support.</strong> Audio input exists only on E2B/E4B/12B. If you want top quality (26B/31B) and audio at the same time, a trade-off arises within the lineup.</li>
  <li><strong>January 2025 training cutoff.</strong> Tasks needing the latest information must be supplemented with RAG and tool integration.</li>
</ul>

<p>Even so, the Apache 2.0 license, the feasibility of single-GPU serving, and a lineup that bridges the edge to the server are reason enough to put Gemma 4 at the top of the evaluation list for any organization considering on-prem and self-hosting.</p>

<h2 id="references">References</h2>

<ul>
  <li><a href="https://blog.google/innovation-and-ai/technology/developers-tools/gemma-4/">Gemma 4 official announcement blog (Google)</a></li>
  <li><a href="https://ai.google.dev/gemma/docs/core/model_card_4">Gemma 4 model card (Google AI for Developers)</a></li>
  <li><a href="https://ai.google.dev/gemma/docs/core">Gemma 4 model overview docs</a></li>
  <li><a href="https://huggingface.co/collections/google/gemma-4">google/gemma-4 collection on Hugging Face</a></li>
  <li><a href="https://github.com/google-deepmind/gemma">Google DeepMind Gemma GitHub library</a></li>
  <li><a href="https://cloud.google.com/blog/products/ai-machine-learning/gemma-4-available-on-google-cloud">Gemma 4 availability on Google Cloud</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="owm" /><category term="gemma-4" /><category term="google-deepmind" /><category term="open-weight" /><category term="apache-2.0" /><category term="mixture-of-experts" /><category term="multimodal" /><category term="edge-ai" /><category term="vllm" /><category term="sglang" /><category term="on-premise" /><summary type="html"><![CDATA[Released by Google DeepMind in April 2026, Gemma 4 is a multimodal open-weight family of five models spanning E2B to 31B. We break down the Apache 2.0 license, 256K context, the difference between the 26B MoE and 31B Dense, and how to pick each model from an on-premises serving perspective.]]></summary></entry><entry xml:lang="ko"><title type="html">Android 에뮬레이터를 컨테이너로 - docker-android로 K8s 위에 재현 가능한 디바이스 팜 만들기</title><link href="https://thakicloud.github.io/ko/dev/docker-android-k8s-emulator/" rel="alternate" type="text/html" title="Android 에뮬레이터를 컨테이너로 - docker-android로 K8s 위에 재현 가능한 디바이스 팜 만들기" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/ko/dev/docker-android-k8s-emulator</id><content type="html" xml:base="https://thakicloud.github.io/ko/dev/docker-android-k8s-emulator/"><![CDATA[<pre><code class="language-mermaid">flowchart LR
    subgraph NODE["KVM 활성 K8s 노드 / Pod"]
      EMU["Android 에뮬레이터 (QEMU + KVM, 옵션 CUDA)"]
      KVM["/dev/kvm"]
    end
    KVM --&gt;|passthrough| EMU
    EMU --&gt; SVC["ADB Service"]
    SVC --&gt; CI["CI 팜"]
    SVC --&gt; SCRCPY["scrcpy 원격 제어"]
</code></pre>
<h2 id="개요">개요</h2>

<p>모바일 앱을 테스트하려면 Android 디바이스가 필요합니다. 실제 단말을 여러 대 두는 방식은 관리가 번거롭고, 로컬에 무거운 에뮬레이터를 까는 방식은 환경이 사람마다 달라져 재현성이 떨어집니다. CI 파이프라인에 Android 테스트를 넣으려고 하면 이 문제는 더 커집니다. 빌드 노드마다 에뮬레이터를 일관되게 깔아야 하기 때문입니다.</p>

<p><code class="language-plaintext highlighter-rouge">docker-android</code>(HQarroum 버전)는 이 문제를 컨테이너로 풉니다. Android 에뮬레이터를 최소 구성으로 패키징해 헤드리스로 띄우고, ADB와 화면 제어를 네트워크 너머로 노출합니다. 컨테이너 한 개로 깨끗하고 일관된 Android 환경을 초 단위로 만들 수 있으므로, CI/CD와 자동화 테스트에 잘 맞습니다.</p>

<p>이 글에서는 docker-android의 구조와 실제 요구사항을 문서 기준으로 확인하고, ThakiCloud의 Kubernetes 플랫폼 관점에서 이런 디바이스 클래스 워크로드를 어떻게 다룰 수 있는지를 정리합니다. AI/ML이 주제인 우리 플랫폼에서 모바일 에뮬레이터가 곧장 핵심은 아니지만, KVM 디바이스 패스스루와 GPU 가속이 필요한 컨테이너 워크로드를 어떻게 격리해 운용하는가라는 질문은 우리 인프라 역량과 직접 닿아 있습니다.</p>

<hr />

<h2 id="docker-android는-무엇인가">docker-android는 무엇인가</h2>

<p>HQarroum의 docker-android는 Alpine 기반의 작은 이미지에 Android 에뮬레이터와 KVM 지원, 그리고 JRE 11을 묶은 프로젝트입니다(현재 버전 1.1.0). 설계 초점은 분명합니다. 네트워크로 원격 제어 가능한 완전한 Android 에뮬레이터를, 최소한의 소프트웨어만으로 노출하는 것입니다. 이미지 안에는 에뮬레이터, 외부에서 접속하기 위한 ADB 서버, 그리고 libvirt를 갖춘 QEMU만 들어갑니다.</p>

<p>주요 특징은 다음과 같습니다.</p>

<ul>
  <li><strong>최소 구성</strong>: Alpine 기반으로 크기를 최적화했습니다. SDK와 에뮬레이터를 빼고 빌드하면 이미지가 훨씬 작아집니다.</li>
  <li><strong>커스터마이즈</strong>: Android 버전, 디바이스 타입, 이미지 종류를 선택할 수 있습니다.</li>
  <li><strong>포트 포워딩 내장</strong>: 에뮬레이터와 ADB를 컨테이너 네트워크 인터페이스로 노출합니다.</li>
  <li><strong>헤드리스</strong>: GUI 없이 동작하므로 CI 팜에 적합합니다. <a href="https://github.com/Genymobile/scrcpy">scrcpy</a>로 화면을 원격 제어할 수 있습니다.</li>
  <li><strong>재현성</strong>: 에뮬레이터 이미지는 재시작할 때마다 초기화됩니다. 매번 같은 상태에서 시작한다는 뜻입니다.</li>
</ul>

<p>위 다이어그램은 이 컨테이너를 ThakiCloud Kubernetes에 배치한 가정 구성입니다. KVM이 활성화된 노드의 파드에 에뮬레이터를 띄우고, <code class="language-plaintext highlighter-rouge">/dev/kvm</code>을 패스스루하며, GPU 가속이 필요하면 cuda 변형을 사용합니다. ADB는 Service로 노출해 CI 팜과 scrcpy가 접근합니다.</p>

<hr />

<h2 id="설치-및-통합">설치 및 통합</h2>

<p>기본 빌드는 Android SDK, 플랫폼 도구, 에뮬레이터를 이미지에 함께 묶습니다. docker-compose로 띄우는 방법은 아래와 같습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 기본 에뮬레이터</span>
docker compose up android-emulator

<span class="c"># GPU 가속</span>
docker compose up android-emulator-cuda

<span class="c"># GPU 가속 + Google Play Store</span>
docker compose up android-emulator-cuda-store
</code></pre></div></div>

<p>docker만 사용해 직접 빌드할 수도 있습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker build <span class="nt">-t</span> android-emulator <span class="nb">.</span>
</code></pre></div></div>

<p>이미지를 빌드한 뒤에는 KVM 드라이브를 마운트해 컨테이너를 실행합니다. Play Store 이미지를 쓰려면 에뮬레이터와 클라이언트가 같은 adbkey를 공유해야 하며, <code class="language-plaintext highlighter-rouge">adb keygen adbkey</code>로 키를 생성해 <code class="language-plaintext highlighter-rouge">./keys</code> 디렉터리에 넣습니다.</p>

<p>이미지 크기는 빌드 변형에 따라 크게 달라집니다. 저장소 문서에 명시된 비교표는 다음과 같습니다.</p>

<table>
  <thead>
    <tr>
      <th>빌드 변형</th>
      <th>압축 해제</th>
      <th>압축</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>API 33 + 에뮬레이터</td>
      <td>5.84 GB</td>
      <td>1.97 GB</td>
    </tr>
    <tr>
      <td>API 32 + 에뮬레이터</td>
      <td>5.89 GB</td>
      <td>1.93 GB</td>
    </tr>
    <tr>
      <td>API 28 + 에뮬레이터</td>
      <td>4.29 GB</td>
      <td>1.46 GB</td>
    </tr>
    <tr>
      <td>SDK·에뮬레이터 제외</td>
      <td>414 MB</td>
      <td>138 MB</td>
    </tr>
  </tbody>
</table>

<p>에뮬레이터를 포함한 이미지는 압축 기준으로도 1.5GB 이상입니다. 다수의 노드에 분산 배포할 때는 레지스트리 대역폭과 노드 디스크를 함께 고려해야 합니다.</p>

<hr />

<h2 id="실제-동작-확인">실제 동작 확인</h2>

<p>이번 글에서는 컨테이너의 실제 부팅까지는 검증하지 못했습니다. 정직하게 기록합니다. 재현 시도 중 실패: 작업 호스트에 Docker 데몬이 없고, macOS는 <code class="language-plaintext highlighter-rouge">/dev/kvm</code>을 제공하지 않아 에뮬레이터 컨테이너가 부팅되지 않습니다. docker-android는 KVM 하드웨어 가속을 요구하므로, 실제 구동은 Linux 호스트 또는 중첩 가상화를 지원하는 KVM 노드에서만 가능합니다.</p>

<p>대신 검증 가능한 사실은 저장소 문서에서 직접 확인했습니다. 위 이미지 크기 비교표는 문서에 명시된 실제 수치이며, 빌드 변형과 compose 서비스 이름, KVM 마운트 요구사항도 문서 기준입니다. 측정하지 못한 부팅 시간이나 테스트 처리량 같은 수치는 만들어 넣지 않았습니다. 실제 도입 단계에서는 KVM 노드를 확보한 뒤 컨테이너 부팅 시간, ADB 연결 지연, 동시 실행 가능한 에뮬레이터 수를 직접 측정하는 절차가 필요합니다.</p>

<hr />

<h2 id="thakicloud-k8s-aiml-saas-플랫폼-적용-및-시사점">ThakiCloud K8s AI/ML SaaS 플랫폼 적용 및 시사점</h2>

<p>docker-android 자체는 AI/ML 도구가 아닙니다. 그러나 이 프로젝트가 드러내는 운영 요구사항은 ThakiCloud가 잘하는 영역과 정확히 겹칩니다.</p>

<p>첫째, <strong>디바이스 패스스루 워크로드의 격리</strong>입니다. 에뮬레이터는 <code class="language-plaintext highlighter-rouge">/dev/kvm</code>을 요구하는 특권 컨테이너에 가깝습니다. K8s에서 이런 디바이스 클래스 워크로드를 멀티테넌트 환경에서 안전하게 격리하려면, 노드 선택, 디바이스 플러그인, 보안 컨텍스트를 신중히 다뤄야 합니다. ThakiCloud는 이미 GPU를 device plugin과 Kueue로 큐잉하고 있으며, KVM 패스스루도 같은 패턴으로 다룰 수 있습니다.</p>

<p>둘째, <strong>재현 가능한 테스트 팜</strong>입니다. 헤드리스 에뮬레이터를 컨테이너로 묶으면, 깨끗한 환경을 노드 수만큼 수평 확장할 수 있습니다. CI/CD에서 Appium UI 테스트를 다수 병렬로 돌리는 구성은 K8s 잡 스케줄링의 전형적인 사용처입니다.</p>

<p>셋째, 더 멀리 보면 <strong>온디바이스 AI 검증</strong>으로 확장할 수 있습니다. 모바일에서 동작하는 경량 모델이나 에이전트의 동작을 자동화로 검증하려면, 격리된 Android 환경을 다수 띄워 회귀 테스트를 돌리는 디바이스 팜이 유용합니다. 현재 우리 플랫폼의 핵심은 아니지만, 멀티테넌트 GPU·디바이스 오케스트레이션 역량이 성숙해지면 이런 모바일 AI QA 팜도 같은 인프라 위에서 제공 가능한 형태로 확장할 수 있습니다.</p>

<p>요약하면, docker-android는 그 자체로 우리 제품은 아니지만 “특권·디바이스·GPU 가속이 얽힌 무거운 컨테이너 워크로드를 K8s에서 어떻게 길들이는가”라는 좋은 사례입니다. 이는 ThakiCloud가 강조하는 범용 K8s 오케스트레이션 역량을 보여 주는 구체적인 그림입니다.</p>

<hr />

<h2 id="한계-및-반론">한계 및 반론</h2>

<ul>
  <li><strong>무거운 의존성</strong>: KVM 하드웨어 가속은 협상 대상이 아닙니다. 중첩 가상화를 지원하지 않는 환경에서는 성능이 급격히 떨어지거나 아예 부팅되지 않습니다. 클라우드 노드 선택이 곧 제약이 됩니다.</li>
  <li><strong>이미지 비대</strong>: 에뮬레이터 포함 이미지는 압축해도 수 GB입니다. 노드 다수에 분산하면 레지스트리와 디스크 비용이 누적됩니다.</li>
  <li><strong>AI/ML 적합성의 거리</strong>: 솔직히 이 도구는 우리 플랫폼의 핵심 워크로드인 학습·추론과는 거리가 있습니다. 모바일 테스트 수요가 없는 조직에는 직접적인 가치가 작습니다. 이 글의 가치는 “에뮬레이터 그 자체”가 아니라 “디바이스 패스스루 컨테이너의 운영 패턴”에 있습니다.</li>
  <li><strong>특권 컨테이너의 보안</strong>: <code class="language-plaintext highlighter-rouge">/dev/kvm</code> 접근과 특권 설정은 멀티테넌트 보안 경계를 복잡하게 만듭니다. 테넌트 격리를 깨지 않으려면 전용 노드 풀과 엄격한 정책이 필요합니다.</li>
</ul>

<p>결론적으로 docker-android는 모바일 테스트 자동화에 강력한 도구이며, 동시에 K8s에서 디바이스 클래스 워크로드를 다루는 방법을 보여 주는 교본입니다. 우리에게 직접 필요한 순간이 오기 전이라도, 그 운영 패턴은 미리 익혀 둘 가치가 있습니다.</p>

<hr />

<h2 id="출처">출처</h2>

<ul>
  <li>docker-android (HQarroum): <a href="https://github.com/HQarroum/docker-android">https://github.com/HQarroum/docker-android</a></li>
  <li>Docker Hub 이미지: <code class="language-plaintext highlighter-rouge">halimqarroum/docker-android</code></li>
  <li>scrcpy (원격 화면 제어): <a href="https://github.com/Genymobile/scrcpy">https://github.com/Genymobile/scrcpy</a></li>
  <li>원 트윗(RT): <a href="https://x.com/hjguyhan/status/2069427245295493446">https://x.com/hjguyhan/status/2069427245295493446</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="dev" /><category term="docker" /><category term="android" /><category term="kubernetes" /><category term="kvm" /><category term="ci-cd" /><summary type="html"><![CDATA[docker-android는 Android 에뮬레이터를 단일 컨테이너로 패키징해 헤드리스로 띄우는 오픈소스 프로젝트입니다. 이미지 크기와 KVM 요구사항을 실제 문서 기준으로 확인하고, ThakiCloud K8s 플랫폼에서 디바이스 패스스루 워크로드를 운용하는 관점을 정리합니다.]]></summary></entry><entry xml:lang="ko"><title type="html">Claude Code를 사내 모델로 라우팅하기 - claude-code-router로 비용 효율적 코딩 인프라 구축</title><link href="https://thakicloud.github.io/ko/llmops/claude-code-router-onprem-routing/" rel="alternate" type="text/html" title="Claude Code를 사내 모델로 라우팅하기 - claude-code-router로 비용 효율적 코딩 인프라 구축" /><published>2026-06-24T00:00:00+09:00</published><updated>2026-06-24T00:00:00+09:00</updated><id>https://thakicloud.github.io/ko/llmops/claude-code-router-onprem-routing</id><content type="html" xml:base="https://thakicloud.github.io/ko/llmops/claude-code-router-onprem-routing/"><![CDATA[<pre><code class="language-mermaid">flowchart LR
    CC["Claude Code"] --&gt; CCR["claude-code-router 프록시"]
    CCR --&gt;|default / background| GLM["Ollama Cloud · glm-5.2"]
    CCR --&gt;|think / longContext| MM["MiniMax-M2.7 (Anthropic 엔드포인트)"]
    CCR -.-&gt;|코딩 서브에이전트 태그| KIMI["Ollama Cloud · kimi-k2.7-code"]
    CCR -.-&gt;|onprem 옵션| VLLM["사내 vLLM (GLM-air)"]
    AUDIT["일일 비용 측정 루프"] --&gt;|Sonnet 대비 효율 검사| CCR
</code></pre>

<h2 id="개요">개요</h2>

<p>Claude Code는 터미널에서 동작하는 에이전트형 코딩 도구입니다. 기본 동작은 Anthropic API로 요청을 보내는 것이지만, 모든 요청이 같은 무게를 갖지는 않습니다. 백그라운드 요약, 짧은 자동완성, 긴 컨텍스트 분석, 깊은 추론이 필요한 리팩터링은 서로 다른 모델 등급을 요구합니다. 모든 요청을 가장 비싼 모델로 처리하면 비용이 빠르게 쌓이고, 반대로 전부 값싼 모델로 처리하면 품질이 무너집니다.</p>

<p><code class="language-plaintext highlighter-rouge">claude-code-router</code>(이하 CCR)는 이 문제를 라우팅 계층으로 풉니다. Claude Code와 모델 백엔드 사이에 프록시를 두고, 요청 종류에 따라 다른 제공자와 모델로 트래픽을 분기합니다. 이 글은 개념 소개에 그치지 않습니다. 실제로 세 개의 외부 모델을 호출해 동작을 검증하고, 그 과정에서 만난 문제(죽은 API 키, thinking 태그 누수)를 고치고, 마지막으로 “이 라우팅이 정말 Anthropic Sonnet보다 싼가”를 상시 측정하는 루프까지 붙인 기록입니다.</p>

<p>핵심 원칙을 먼저 박아 둡니다. <strong>CCR로 보내는 모든 모델은 Claude Sonnet보다 비용 효율적일 때만 의미가 있습니다.</strong> 그렇지 않다면 품질만 떨어뜨리고 돈은 그대로 나가는 셈입니다. 그래서 단정하지 않고 측정합니다.</p>

<hr />

<h2 id="claude-code-router는-무엇인가">claude-code-router는 무엇인가</h2>

<p>CCR은 Anthropic 메시지 형식의 요청을 받아 OpenAI 호환 형식 등으로 변환한 뒤 설정된 제공자로 전달하는 프록시 서버입니다. Claude Code 클라이언트 자체는 건드리지 않습니다. <code class="language-plaintext highlighter-rouge">ccr code</code>로 세션을 띄우면 그 세션의 트래픽이 <code class="language-plaintext highlighter-rouge">localhost:3456</code> 프록시를 거쳐 라우팅됩니다.</p>

<p>핵심 기능은 다음과 같습니다.</p>

<ul>
  <li><strong>요청 유형별 라우팅</strong>: <code class="language-plaintext highlighter-rouge">default</code>, <code class="language-plaintext highlighter-rouge">background</code>, <code class="language-plaintext highlighter-rouge">think</code>, <code class="language-plaintext highlighter-rouge">longContext</code>, <code class="language-plaintext highlighter-rouge">webSearch</code> 등 유형마다 다른 모델을 지정합니다.</li>
  <li><strong>멀티 제공자</strong>: OpenAI 호환 엔드포인트면 무엇이든 등록할 수 있습니다. 이번에는 Ollama Cloud와 MiniMax를 씁니다.</li>
  <li><strong>transformer</strong>: 제공자마다 다른 API 규격을 변환기가 흡수합니다. Anthropic 네이티브 엔드포인트를 위한 <code class="language-plaintext highlighter-rouge">Anthropic</code> 패스스루 변환기가 이 글의 핵심 도구로 등장합니다.</li>
  <li><strong>동적 전환</strong>: 세션 안에서 <code class="language-plaintext highlighter-rouge">/model provider,model</code> 명령으로 즉시 모델을 바꿉니다.</li>
</ul>

<p>검증에 사용한 CCR 버전은 <code class="language-plaintext highlighter-rouge">1.0.62</code>입니다. 설정 파일은 <code class="language-plaintext highlighter-rouge">~/.claude-code-router/config.json</code>이며, 핵심은 <code class="language-plaintext highlighter-rouge">Providers</code> 배열과 <code class="language-plaintext highlighter-rouge">Router</code> 객체입니다.</p>

<hr />

<h2 id="무엇을-라우팅하는가---세-모델로-고정">무엇을 라우팅하는가 - 세 모델로 고정</h2>

<p>이번 구성의 모델 풀은 정확히 세 개입니다. 모델을 늘리면 라우팅 표가 복잡해지고 검증 비용이 커지므로 의도적으로 좁혔습니다.</p>

<table>
  <thead>
    <tr>
      <th>역할</th>
      <th>모델</th>
      <th>제공자</th>
      <th>비고</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>주력 (default·background)</td>
      <td><code class="language-plaintext highlighter-rouge">glm-5.2</code></td>
      <td>Ollama Cloud</td>
      <td>일상 코딩, 강력하고 저렴</td>
    </tr>
    <tr>
      <td>추론 (think·longContext)</td>
      <td><code class="language-plaintext highlighter-rouge">MiniMax-M2.7</code></td>
      <td>MiniMax</td>
      <td>thinking 분리, per-token이 매우 저렴</td>
    </tr>
    <tr>
      <td>코딩 서브에이전트</td>
      <td><code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code></td>
      <td>Ollama Cloud</td>
      <td>어려운 코딩 턴 전용</td>
    </tr>
  </tbody>
</table>

<p><code class="language-plaintext highlighter-rouge">glm-5.2</code>를 주력으로 두고, 깊은 추론과 긴 컨텍스트만 MiniMax로, 까다로운 코딩 한 턴은 Kimi로 보내는 구조입니다.</p>

<hr />

<h2 id="실제-검증-결과---가정하지-않고-호출했다">실제 검증 결과 - 가정하지 않고 호출했다</h2>

<p>설정을 쓰기 전에 세 모델을 직접 호출했습니다. 추정 수치를 적지 않기 위해 실제 응답을 확인했고, 그 과정에서 세 가지 사실이 드러났습니다.</p>

<p><strong>첫째, Ollama Cloud 키 하나가 GLM과 Kimi를 모두 커버합니다.</strong> <code class="language-plaintext highlighter-rouge">glm-5.2</code>와 <code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code> 모두 <code class="language-plaintext highlighter-rouge">https://ollama.com/v1</code>에서 정상 응답(HTTP 200)했습니다. Ollama Cloud는 GLM, Kimi, DeepSeek, Qwen 계열을 한 키로 묶어 제공합니다.</p>

<p><strong>둘째, 단독 Kimi 키는 죽어 있었습니다.</strong> <code class="language-plaintext highlighter-rouge">.env</code>에 넣어 둔 Moonshot 단독 키는 moonshot.ai, moonshot.cn, Anthropic 호환 엔드포인트 모두에서 401(Invalid Authentication)을 반환했습니다. 다행히 Kimi K2는 Ollama Cloud의 <code class="language-plaintext highlighter-rouge">kimi-k2.7-code</code>로 동일하게 쓸 수 있어, 죽은 키는 막다른 길이 아니었습니다.</p>

<p><strong>셋째, MiniMax는 엔드포인트 선택이 품질을 가릅니다.</strong> OpenAI 호환 엔드포인트(<code class="language-plaintext highlighter-rouge">/v1/chat/completions</code>)로 부르면 모델이 추론을 <code class="language-plaintext highlighter-rouge">&lt;think&gt;...&lt;/think&gt;</code> 태그로 응답 본문에 인라인해 버리고, CCR의 변환 레이어가 이를 떼어내지 못해 그대로 사용자에게 노출됩니다(musistudio/claude-code-router#964). 같은 모델을 네이티브 Anthropic 엔드포인트(<code class="language-plaintext highlighter-rouge">/anthropic/v1/messages</code>)로 부르면 응답이 <code class="language-plaintext highlighter-rouge">thinking</code> 블록과 <code class="language-plaintext highlighter-rouge">text</code> 블록으로 깔끔하게 분리되어 옵니다.</p>

<p>마지막 항목은 단순히 “MiniMax를 빼자”로 끝낼 문제가 아니라 고쳐야 할 버그였습니다. 해결책은 아래 설정에 반영했습니다.</p>

<hr />

<h2 id="설정---비밀키는-저장소-밖-설정은-코드로-생성">설정 - 비밀키는 저장소 밖, 설정은 코드로 생성</h2>

<p>키를 설정 파일에 직접 박지 않습니다. 저장소의 <code class="language-plaintext highlighter-rouge">.env</code>를 읽어 <code class="language-plaintext highlighter-rouge">~/.claude-code-router/config.json</code>을 만드는 생성기 스크립트를 두었습니다. 저장소에는 키가 남지 않고, 키를 교체하면 스크립트만 다시 돌리면 됩니다.</p>

<p>생성되는 핵심 설정은 다음과 같습니다.</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"LOG"</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span><span class="w">
  </span><span class="nl">"HOST"</span><span class="p">:</span><span class="w"> </span><span class="s2">"127.0.0.1"</span><span class="p">,</span><span class="w">
  </span><span class="nl">"PORT"</span><span class="p">:</span><span class="w"> </span><span class="mi">3456</span><span class="p">,</span><span class="w">
  </span><span class="nl">"API_TIMEOUT_MS"</span><span class="p">:</span><span class="w"> </span><span class="mi">1800000</span><span class="p">,</span><span class="w">
  </span><span class="nl">"Providers"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://ollama.com/v1/chat/completions"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;OLLAMA_GLM_API_KEY&gt;"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"glm-5.2"</span><span class="p">,</span><span class="w"> </span><span class="s2">"kimi-k2.7-code"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"transformer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"use"</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="s2">"maxtoken"</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"max_tokens"</span><span class="p">:</span><span class="w"> </span><span class="mi">16000</span><span class="w"> </span><span class="p">}]]</span><span class="w"> </span><span class="p">}</span><span class="w">
    </span><span class="p">},</span><span class="w">
    </span><span class="p">{</span><span class="w">
      </span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_base_url"</span><span class="p">:</span><span class="w"> </span><span class="s2">"https://api.minimax.io/anthropic/v1/messages"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"api_key"</span><span class="p">:</span><span class="w"> </span><span class="s2">"&lt;MINIMAX_API_KEY&gt;"</span><span class="p">,</span><span class="w">
      </span><span class="nl">"models"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"MiniMax-M2.7"</span><span class="p">],</span><span class="w">
      </span><span class="nl">"transformer"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nl">"use"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Anthropic"</span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w">
    </span><span class="p">}</span><span class="w">
  </span><span class="p">],</span><span class="w">
  </span><span class="nl">"Router"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"default"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"background"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"think"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax,MiniMax-M2.7"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"longContext"</span><span class="p">:</span><span class="w"> </span><span class="s2">"minimax,MiniMax-M2.7"</span><span class="p">,</span><span class="w">
    </span><span class="nl">"longContextThreshold"</span><span class="p">:</span><span class="w"> </span><span class="mi">60000</span><span class="p">,</span><span class="w">
    </span><span class="nl">"webSearch"</span><span class="p">:</span><span class="w"> </span><span class="s2">"ollama,glm-5.2"</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>MiniMax provider의 두 줄이 thinking 누수를 해결한 핵심입니다. <code class="language-plaintext highlighter-rouge">api_base_url</code>을 네이티브 Anthropic 경로로 두고 <code class="language-plaintext highlighter-rouge">Anthropic</code> 패스스루 변환기를 쓰면, MiniMax가 처음부터 Anthropic 메시지 형식(<code class="language-plaintext highlighter-rouge">thinking</code> + <code class="language-plaintext highlighter-rouge">text</code> 블록)으로 응답합니다. 프록시를 통과시켜 다시 확인했을 때 응답 블록은 <code class="language-plaintext highlighter-rouge">["thinking", "text"]</code>였고 <code class="language-plaintext highlighter-rouge">&lt;think&gt;</code> 누수는 0이었습니다.</p>

<p>추론 모델은 출력이 느리므로 타임아웃을 넉넉히(<code class="language-plaintext highlighter-rouge">1800000ms</code>) 잡고, GLM·Kimi처럼 추론을 먼저 토해내는 모델이 본문 전에 토큰을 소진하지 않도록 <code class="language-plaintext highlighter-rouge">maxtoken</code>으로 출력 헤드룸을 확보했습니다.</p>

<p>서브에이전트는 설정이 아니라 프롬프트 선두 태그로 분기합니다. 어려운 코딩 작업을 위임할 때는 프롬프트 맨 앞에 <code class="language-plaintext highlighter-rouge">&lt;CCR-SUBAGENT-MODEL&gt;ollama,kimi-k2.7-code&lt;/CCR-SUBAGENT-MODEL&gt;</code>를 붙입니다.</p>

<hr />

<h2 id="어디에-어떻게-연결하는가">어디에 어떻게 연결하는가</h2>

<p>연결 지점은 하나입니다. 작업할 저장소에서 <code class="language-plaintext highlighter-rouge">ccr code</code>로 세션을 시작하면 그 세션의 메인과 서브 트래픽 전부가 프록시를 거쳐 위 라우팅대로 흐릅니다. 네이티브 <code class="language-plaintext highlighter-rouge">claude</code>는 그대로 Anthropic에 직결되므로 영향이 없습니다.</p>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 설정 생성 후 라우터 기동</span>
python3 scripts/ccr/gen_ccr_config.py <span class="o">&amp;&amp;</span> ccr restart

<span class="c"># 비용 라우팅 세션 시작 (이게 연결 지점)</span>
ccr code

<span class="c"># 세션 안에서 작업별로 모델 즉시 전환</span>
/model ollama,kimi-k2.7-code     <span class="c"># 어려운 코딩 턴</span>
/model minimax,MiniMax-M2.7      <span class="c"># 깊은 추론 턴</span>
/model ollama,glm-5.2            <span class="c"># 일상 코딩</span>
</code></pre></div></div>

<p>비용 효율 관점에서 권장하는 사용 패턴은 하이브리드입니다. 대량·반복·AFK 성격의 작업(테스트 생성, 일괄 리팩터, 로그 분석, 번역, 코드 탐색)은 <code class="language-plaintext highlighter-rouge">ccr code</code>로 돌려 비용을 깎고, 아키텍처 결정이나 미묘한 디버깅처럼 판단이 어려운 작업만 네이티브 <code class="language-plaintext highlighter-rouge">claude</code> 구독 세션으로 처리합니다. 일상 전체를 라우팅 세션으로 옮기면 메인이 GLM이 되어 어려운 작업의 품질이 떨어질 수 있기 때문입니다.</p>

<hr />

<h2 id="비용-효율---sonnet보다-싼지-상시-측정한다">비용 효율 - Sonnet보다 싼지 상시 측정한다</h2>

<p>이 구성의 존재 이유는 비용입니다. 그래서 “싸다”고 주장하지 않고 측정합니다.</p>

<p>2026년 6월 24일 기준 확인한 단가입니다(100만 토큰당 USD).</p>

<table>
  <thead>
    <tr>
      <th>모델</th>
      <th>입력</th>
      <th>출력</th>
      <th>과금 형태</th>
      <th>Sonnet 대비</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Claude Sonnet 4.6 (기준)</td>
      <td>$3.00</td>
      <td>$15.00</td>
      <td>per-token</td>
      <td>1.0배</td>
    </tr>
    <tr>
      <td>MiniMax-M2.7</td>
      <td>$0.24</td>
      <td>$0.96</td>
      <td>per-token</td>
      <td>약 0.07배</td>
    </tr>
    <tr>
      <td>glm-5.2 / kimi-k2.7-code</td>
      <td>—</td>
      <td>—</td>
      <td>구독 $20/월(Pro)</td>
      <td>사용량 의존</td>
    </tr>
  </tbody>
</table>

<p>MiniMax-M2.7은 토큰당 단가가 Sonnet의 7~8% 수준이라 언제나 압도적으로 쌉니다. 반면 Ollama Cloud는 토큰당이 아니라 월정액 구독제입니다. 즉 실효 단가는 <code class="language-plaintext highlighter-rouge">월 요금 ÷ 월 사용 토큰</code>이고, 적게 쓰면 $20 정액이 오히려 손해입니다. blended $9/M 기준으로 계산하면 <strong>월 약 220만 토큰을 넘겨야</strong> Sonnet보다 싸집니다.</p>

<p>이 손익분기는 추정이 아니라 측정 대상입니다. CCR 로그에는 요청마다 라우팅된 모델과 입출력 토큰이 남습니다. 이를 집계해 per-token 모델은 실제 비용 대 Sonnet 환산 비용의 비율을, 구독 모델은 월 투영 Sonnet 비용 대 구독료를 비교하는 측정 스크립트를 두었습니다. 측정 결과는 이력 파일에 누적되어 추세를 봅니다. 개선이란 시간이 지나며 비율이 더 낮아지는 것입니다.</p>

<p>이 루프는 launchd로 매일 한 번 자동 실행됩니다. Claude를 루프에 두지 않고 순수 스크립트만 cron으로 돌리므로 측정 자체의 비용은 0입니다. 측정에서 per-token 모델이 Sonnet보다 비싸지는 이상 신호가 잡히면 사내 Slack으로 경보가 갑니다. 구독 모델이 손익분기에 미달하는 저사용 상태는 경보 대신 리포트에만 남겨 램프업 초기의 잡음을 막습니다.</p>

<p>행동 규칙도 측정에 묶여 있습니다. per-token 모델의 비율이 1.0 이상이면(즉 Sonnet보다 비싸지면) 그 모델은 즉시 라우팅에서 내립니다. 구독 모델이 여러 달 저사용이면 플랜을 낮추거나 그 경로를 저가 per-token 모델로 바꿉니다. 단가가 바뀌면 가격표 파일만 갱신하면 다음 측정부터 반영됩니다.</p>

<hr />

<h2 id="thakicloud-플랫폼-관점">ThakiCloud 플랫폼 관점</h2>

<p>이 라우팅 모델은 ThakiCloud가 이미 운용하는 인프라와 자연스럽게 맞물립니다.</p>

<p><strong>코드 보안</strong>입니다. 금융, 공공, 의료처럼 소스 코드 외부 반출이 제한되는 환경에서는 위 설정의 <code class="language-plaintext highlighter-rouge">default</code>를 사내 vLLM 엔드포인트로 바꾸기만 하면 됩니다. Claude Code의 사용성을 유지하면서 프롬프트와 코드가 외부로 나가지 않는 구성이 됩니다. 이번 글의 외부 모델 구성은 비용 검증용이고, 같은 골격에 사내 GPU 서빙을 끼우면 온프레미스 버전이 됩니다.</p>

<p><strong>비용 통제</strong>입니다. 작업별 라우팅은 곧 비용별 라우팅입니다. 빈도는 높지만 난도는 낮은 요청을 저가 모델로 보내고 고난도 추론만 상위 모델로 보내면, 비싼 모델 사용량을 실제로 필요한 곳으로 좁힐 수 있습니다. 그리고 그 효과를 측정 루프가 숫자로 증명합니다.</p>

<p><strong>정책의 코드화</strong>입니다. 제공자와 라우팅 규칙, 가격표, 측정 기준이 모두 텍스트 파일로 관리되고 저장소에 커밋됩니다. 키만 <code class="language-plaintext highlighter-rouge">.env</code>에 남고 설정은 생성기로 재현되므로, 다른 머신에서도 같은 구성이 복원됩니다.</p>

<hr />

<h2 id="한계-및-반론">한계 및 반론</h2>

<p>라우터를 도입한다고 모든 문제가 풀리지는 않습니다. 냉정하게 볼 지점이 여럿 있습니다.</p>

<ul>
  <li><strong>품질 격차</strong>: 라우팅의 가치는 백엔드 모델 품질에 종속됩니다. 복잡한 멀티스텝 리팩터링이나 미묘한 디버깅에서 오픈 모델이 상위 폐쇄 모델을 늘 따라잡지는 못합니다. 그래서 하이브리드를 권합니다.</li>
  <li><strong>도구 호출 신뢰도</strong>: Claude Code는 도구 호출에 크게 의존합니다. OpenAI 호환 변환 레이어를 거치면 도구 호출 포맷이 흔들릴 수 있어, 탐색·요약 서브에이전트에는 안전하지만 편집·구현 서브에이전트에는 단계적 확대가 안전합니다.</li>
  <li><strong>구독제의 함정</strong>: Ollama Cloud는 정액이라 적게 쓰면 손해입니다. 손익분기를 넘기지 못하면 차라리 Sonnet이 쌉니다. 측정 루프가 바로 이 지점을 감시합니다.</li>
  <li><strong>프록시는 단일 장애점</strong>: 메인 트래픽도 CCR을 통과하므로 프록시가 죽으면 세션이 멈춥니다. 폴백은 네이티브 <code class="language-plaintext highlighter-rouge">claude</code>입니다.</li>
  <li><strong>“무료” 프레이밍의 함정</strong>: 일부 변형판은 텔레메트리나 안전 가드 제거를 내세우며 “무료”를 강조합니다. 회사가 권장할 수 없는 방향입니다. 우리가 취하는 가치는 무료가 아니라 통제권, 즉 어떤 요청을 어떤 모델로 보낼지를 우리가 정하고 그 비용을 우리가 측정한다는 점입니다.</li>
</ul>

<p>결론적으로 CCR은 비용을 줄이는 마법이 아니라 라우팅이라는 통제 장치입니다. 그 통제권을 검증된 모델 풀, thinking 누수 같은 실제 버그의 수정, 그리고 Sonnet 대비 상시 측정과 결합할 때 비로소 보안과 비용 양쪽에서 의미 있는 이득이 됩니다.</p>

<hr />

<h2 id="출처">출처</h2>

<ul>
  <li>claude-code-router (musistudio): <a href="https://github.com/musistudio/claude-code-router">https://github.com/musistudio/claude-code-router</a></li>
  <li>MiniMax thinking 누수 이슈: <a href="https://github.com/musistudio/claude-code-router/issues/964">claude-code-router#964</a></li>
  <li>MiniMax M2.7 단가: <a href="https://openrouter.ai/minimax/minimax-m2.7">openrouter.ai/minimax/minimax-m2.7</a></li>
  <li>Ollama Cloud 요금: <a href="https://ollama.com/pricing">ollama.com/pricing</a></li>
  <li>Claude API 단가: <a href="https://platform.claude.com/docs/en/about-claude/pricing">platform.claude.com/docs pricing</a></li>
</ul>]]></content><author><name>{&quot;name&quot;=&gt;nil, &quot;avatar&quot;=&gt;nil, &quot;bio&quot;=&gt;nil, &quot;location&quot;=&gt;&quot;Seoul, Korea&quot;, &quot;email&quot;=&gt;&quot;info@thakicloud.co.kr&quot;, &quot;uri&quot;=&gt;nil, &quot;home&quot;=&gt;nil, &quot;links&quot;=&gt;[{&quot;label&quot;=&gt;&quot;Website&quot;, &quot;icon&quot;=&gt;&quot;fas fa-fw fa-link&quot;, &quot;url&quot;=&gt;&quot;https://thakicloud.co.kr&quot;}, {&quot;label&quot;=&gt;&quot;GitHub&quot;, &quot;icon&quot;=&gt;&quot;fab fa-fw fa-github&quot;, &quot;url&quot;=&gt;&quot;https://github.com/thakicloud&quot;}]}</name><email>info@thakicloud.co.kr</email></author><category term="llmops" /><category term="claude-code" /><category term="model-routing" /><category term="cost-optimization" /><category term="ollama" /><category term="minimax" /><category term="on-premise" /><summary type="html"><![CDATA[claude-code-router로 Claude Code 트래픽을 glm-5.2·MiniMax-M2.7·Kimi K2로 분기합니다. 세 모델을 실제로 호출해 검증하고, MiniMax thinking 누수를 고치고, 모든 라우팅 모델이 Sonnet보다 싼지 상시 측정하는 루프까지 구축한 실전 기록입니다.]]></summary></entry></feed>