
kuri v0.4.12
أتمتة المتصفح، زحف الويب، والتحكم في أجهزة iOS + Android لوكلاء الذكاء الاصطناعي. لقطات CDP أصلية بلغة Zig وموفرة للرموز، تسجيل HAR، عميل adb wire-protocol الأصلي، وأداة جلب مستقلة.
Kuri 🌰
التثبيت```sh
curl -fsSL https://kuri.trilok.ai/download | sh
يدعم macOS arm64/x86_64 وLinux x86_64/arm64. ملف ثنائي واحد، بدون تبعيات وقت التشغيل.
روابط تنزيل مباشرة: [macOS arm64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-aarch64-macos.tar.gz) · [macOS x86_64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-x86_64-macos.tar.gz) · [Linux x86_64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-x86_64-linux.tar.gz) · [Linux arm64](https://kuri.trilok.ai/download/v0.6.0/kuri-v0.6.0-aarch64-linux.tar.gz)
---
**أتمتة المتصفح وزحف الويب لوكلاء الذكاء الاصطناعي. مكتوب بلغة Zig. صفر Node.js.**
أتمتة CDP · لقطات A11y · تسجيل HAR · جالب مستقل · متصفح طرفية تفاعلي · واجهة أوامر وكيلية · اختبار الأمان · التحكم في أجهزة iOS وAndroid
[بدء سريع](#-quick-start) · [المعايير](#-benchmarks) · [kuri-agent](#-kuri-agent) · [اختبار الأمان](#-security-testing) · [API](#-http-api) · [المهارات](#-skills) · [سجل التغييرات](https://github.com/justrach/kuri/blob/HEAD/CHANGELOG.md)
> **لماذا تنتقل الفرق إلى Kuri:** تبقى إصدارات `ReleaseFast` الحالية على Apple Silicon أقل من 2 ميغابايت لكل ملف ثنائي، وأظهرت إعادة تشغيل جديدة لـ Google Flights في 2026-04-23 **3,392 توكنًا** لدورة `kuri-agent` كاملة (`go→snap→click→snap→eval`). يجب إعادة قياس الفروقات بين الأدوات في البيئة نفسها قبل الاستشهاد بأي نسبة مئوية.
---
## لماذا تتفوق Kuri للوكلاء
معظم أدوات المتصفح بُنيت لمهندسي ضمان الجودة (QA). أما Kuri فبُنيت لدورات الوكلاء: اقرأ الصفحة، أبقِ تكلفة التوكنات منخفضة، نفّذ الإجراءات على مراجع ثابتة، وامضِ قدمًا.
- **135 نقطة نهاية HTTP** — تكافؤ كامل مع agent-browser وbrowser-use، من فحص React إلى Core Web Vitals.
- **توكنات أقل بنسبة 7-12%** من agent-browser على الصفحات الحقيقية بفضل صيغة مراجع `@eN` والعرض بدون بادئة.
- **ملاحظات أخف بـ44 مرة** عبر `/page/state` (48 توكنًا) مقابل اللقطة الكاملة (2,124 توكنًا) لنفس صفحة Google Flights.
- **تنفيذ الدفعات** — يرسل `POST /batch` N من الأوامر في استدعاء HTTP واحد، مما يلغي N-1 رحلة ذهاب وعودة وN-1 دورة LLM.
- **متوافق مع React** — أحداث الفأرة CDP الموثوقة وأحداث المفاتيح لكل حرف تُطلق `onClick` و`onChange` في React 18/19.
### توكنات اللقطة: Google Flights `SIN → TPE`
إعادة تشغيل جديدة في 2026-05-24 في مساحة العمل هذه، قِيسَت باستخدام `wc -c` وتقريب `chars/4`.
| الأداة / الوضع | الأحرف | ~التوكنات | ملاحظة |
|---|---:|---:|---|
| `kuri snap` (كامل) | 8,499 | **2,124** | كل العقد + المراجع التفاعلية |
| `kuri snap` (تفاعلي فقط) | ~3,000 | **~750** | الأفضل لدورات الوكلاء |
| `kuri /page/state` | 190 | **48** | ملاحظة خفيفة (url، title، scroll%، counts) |
| لقطة agent-browser (تقديرية) | ~9,183 | **~2,295** | عبء صيغة `[ref=e0]` |
### كفاءة التوكنات: kuri مقابل agent-browser
| الصفحة | توكنات kuri | توكنات agent-browser | التوفير |
|---|---:|---:|---|
| example.com | 40 | 35 | -13% (صفحة بسيطة، يتخطى agent-browser الجذر) |
| Hacker News | 386 | ~440 | **أقل بنسبة 12%** |
| Google Flights SIN→TPE | 2,124 | ~2,295 | **أقل بنسبة 7%** |
يأتي التوفير من صيغة kuri المدمجة:
- مراجع `@e0` (3 أحرف) مقابل `[ref=e0]` (9 أحرف)
- لا بادئة `- ` لكل سطر (يوفر حرفين × عدد الأسطر)
- نفس الإزاحة البادئة، نفس تصفية العقد
### تكلفة سير العمل الكامل: `go → snap → click → snap → eval`
| الأداة | التوكنات لكل دورة |
|---|---:|
| **kuri-agent** | **~3,400** |
| مع `/page/state` بدلاً من اللقطة الثانية | **~1,700** |
| مع `POST /batch` (كل شيء في استدعاء واحد) | **~1,700** (نفس التوكنات، استدعاء HTTP واحد بدلاً من 5) |
### kuri مقابل libretto
[libretto](https://github.com/saffron-health/libretto) (Playwright + Node) هو أقرب منافس من حيث تكلفة التوكنات لكل خطوة. قِيس وجهاً لوجه في 2026-07-04 — نفس Chrome، نفس التبويب، أعداد فعلية من `tiktoken` `o200k_base` (المنهجية الكاملة وإعادة الإنتاج: **[benchmarks/libretto_comparison.md](https://github.com/justrach/kuri/blob/HEAD/benchmarks/libretto_comparison.md)**). التقسيم الصادق:
| المحور | الفائز | التفاصيل |
|---|---|---|
| زمن الاستجابة لكل استدعاء | **kuri** | 4–117 مللي ثانية مقابل 1,344–1,500 مللي ثانية (**أسرع بـ13–376 مرة** — خادم مستمر مقابل Node لكل أمر) |
| توكنات اللقطة، صفحة نموذجية | **kuri** | بسيطة 61 مقابل 151 (2.5×)، مقالة 265 مقابل 363 (1.37×) — صياغة أكثر إحكامًا |
| توكنات اللقطة، قائمة كبيرة | انقسام | افتراضي kuri 4,424 مقابل 813 — يصدر kuri كل المراجع الـ259 بينما يقصّها libretto افتراضيًا. مع `limit=5` يعرض kuri 555 توكنًا (**أقل بـ1.46 مرة من libretto**)، 34 مرجعًا + علامات `… +45 more` |
| المسار (feed، 9 نقرات) | **kuri**، بفارق ضئيل | 898 مقابل 939 توكنًا (أساس `limit=5` + حلقة الفروق مقابل حلقة التنفيذ) — تكافؤ إلى أفضلية طفيفة؛ خسارة 5.1× صباحًا كانت بسبب الأساس غير المقصوص |
| التشغيلات المتكررة | **libretto** | يجمّع المسارات في سكربت Playwright → إعادة تشغيل بـ0 توكن؛ بينما يدفع kuri ثمن الدورة في كل تشغيل |
**ما جنته kuri من دراسة libretto** (وكل ذلك صار ضمن هذا الإصدار): حلقة تعتمد الفروق أولًا (`take_snapshot_diff`، ~38 توكنًا لكل خطوة)؛ فرق تكيفي يتراجع إلى لقطة كاملة مع ترويسة `! page replaced` عند التنقل؛ أسطر إزالة تعتمد الهوية فقط؛ لقطات شاشة تُكتب إلى القرص (يُعاد المسار، ولا تدخل البايتات إلى السياق أبدًا)؛ `get_page_state` عبر MCP؛ وبعد إعادة كتابة `parseA11yNodes` كاجتياز حقيقي لشجرة DFS — **قصّ القوائم عند الطلب** (`/snapshot?limit=N`، سطر `… +K more` واحد لكل تشغيل مقصوص)، **إعادة التقاط بنطاق محدد** (`scope=@ref`)، و**المسافات البادئة الهرمية**، المتاحة أيضًا كـ`uid`/`limit` في MCP `take_snapshot`. المسار ذو النقرات التسع (feed) الذي كلّف 44,285 توكنًا مع إعادة لقطات كاملة ساذجة يكلف الآن **898** مع أساس مقصوص + فروق — أرخص بـ49 مرة، وأقل من 939 لدى libretto.
> تستخدم الجداول السابقة أعلاه تقريب توكنات `chars/4`؛ بينما تستخدم مقارنة libretto أعداد `tiktoken` الفعلية. أعد تشغيل الأرقام بين الأدوات في بيئتك الخاصة قبل الاستشهاد بنسبة مئوية.
### حجم الملف الثنائي والذاكرة
قِيس على Apple M4 Pro بنظام macOS 26.4.1. بُنيت الملفات الثنائية الحالية باستخدام `-Doptimize=ReleaseFast`.
| الملف الثنائي | الحجم الحالي |
|---|---:|
| `kuri` | 1,093,840 B (1.04 MiB) |
| `kuri-agent` | 629,904 B (615 KiB) |
| `kuri-browse` | 1,089,120 B (1.04 MiB) |
| `kuri-fetch` | 2,063,488 B (1.97 MiB) |
### بقيت RSS ثابتة عبر الانتقال إلى Zig 0.16
قِيس على إصدار `v0.4.3` الحالي المبني بـ `ReleaseFast` باستخدام `/usr/bin/time -l`.
| الأمر | متوسط أقصى RSS في `v0.4.3` |
|---|---:|
| `kuri-fetch --version` | ~2.45 MiB |
| `kuri-browse --version` | ~2.45 MiB |
| `kuri-fetch --quiet --dump markdown http://example.com/` | ~9.17 MiB |
## المشكلة
كل أداة أتمتة متصفح تجرّ معها Playwright (~300 ميغابايت)، وبيئة تشغيل Node.js، وسلسلة من تبعيات npm. وكيل الذكاء الاصطناعي لديك يريد فقط قراءة صفحة، والنقر على زر، والمضي قدمًا.
**Kuri ملف ثنائي واحد بلغة Zig.** أربعة أوضاع، صفر بيئة تشغيل:```
kuri → CDP server (Chrome automation, a11y snapshots, HAR)
kuri-fetch → standalone fetcher (no Chrome, QuickJS for JS, ~2 MB)
kuri-browse → interactive terminal browser (navigate, follow links, search)
kuri-agent → agentic CLI (scriptable Chrome automation + security testing)
📦 التثبيت
التثبيت بسطر واحد (macOS / Linux)```sh
curl -fsSL https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/install.sh | sh
يكتشف منصتك، وينزّل الثنائي الصحيح، ويثبّته في `~/.local/bin`.
تأتي التنزيلات من فرع `release-channel` المُدار ذاتيًا من Kuri. ثنائيات macOS موقّعة محليًا بشهادة Developer ID. أصول GitHub Release تعكس نفس هذه الـ tarballs.
### bun / npm```sh
bun install -g kuri-agent
# or: npm install -g kuri-agent
يقوم بتنزيل الثنائي الأصلي المناسب لمنصتك في وقت التثبيت.
قناة الإصدار
تعيش الثنائيات المستقرة من Kuri على فرع release-channel ويتم تقديمها مباشرة من روابط GitHub الخام.
- المثبت المستقر:
https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/install.sh - المانيفست المستقر:
https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/latest.json - عرض الفرع:
https://github.com/justrach/kuri/tree/release-channel/stable - نمط التنزيل المباشر:
https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/<version>/kuri-<version>-<target>.tar.gz
الطريقة اليدوية
قم بتنزيل ملف tarball الخاص بمنصتك من قائمة الإصدار المستقرة أو من صفحة إصدارات GitHub وفك ضغطه إلى $PATH لديك.
رابط التثبيت المستقر:```sh curl -fsSL https://raw.githubusercontent.com/justrach/kuri/release-channel/stable/install.sh | sh
يتضمن المانيفست عناوين URL الدقيقة للأصول بالإضافة إلى مجموعات فحص SHA-256 لكل من `aarch64-linux` و`x86_64-linux` و`aarch64-macos` و`x86_64-macos`.
### دعم المنصات
| المنصة | الحالة |
|---|---|
| macOS (`aarch64`, `x86_64`) | ملفات ثنائية مُجمَّعة مسبقًا، موقّعة وموثّقة |
| Linux (`aarch64`, `x86_64`) | ملفات ثنائية مُجمَّعة مسبقًا |
| Windows (`x86_64`) | **تجريبي — للتجميع المتقاطع فقط.** `zig build -Dtarget=x86_64-windows-gnu` مُتحقَّق منه في CI، لكن أتمتة Chrome، والتحويل إلى خدمة خلفية، وإيقاف التشغيل المعتمد على الإشارات، وتسجيل HAR، ومخزن المصادقة المدعوم بملفات؛ كلها مجرد هياكل مؤقتة تُرجع `error.UnsupportedOnWindows` عند التشغيل. استخدم **WSL2** إذا كنت بحاجة إلى مجموعة الميزات الفعلية. يُتتبَّع في [#153](https://github.com/justrach/kuri/issues/153). |
تعتمد Kuri على بدائيات POSIX (`fork`, `clock_gettime`, والمقابس الخام) في عدة مواضع، لذا فإن النقل الأصلي الكامل إلى Windows يستلزم عملًا حقيقيًا. خط الأساس التجميعي أعلاه يسمح لمسارات `--version`/`--help` والعمليات التي تتم داخل الذاكرة فقط بالعمل؛ أما الأجزاء الشائكة (Chrome، والمقابس، والتحويل إلى خدمة خلفية) فتحتاج إلى تطبيقات Win32 حقيقية قبل إزالتها من قائمة الهياكل المؤقتة. إذا كنت ترغب في تولي أيٍّ منها، أضف +1 إلى [#153](https://github.com/justrach/kuri/issues/153) أو افتح طلب سحب (PR).
### البناء من المصدر
يتطلب [Zig ≥ 0.16.0](https://ziglang.org/download/).```bash
git clone https://github.com/justrach/kuri.git
cd kuri
zig build -Doptimize=ReleaseFast
# Binaries in zig-out/bin/: kuri kuri-agent kuri-fetch kuri-browse
⚡ بدء سريع
المتطلبات: Zig ≥ 0.16.0 · Chrome/Chromium (لوضع CDP)```bash git clone https://github.com/justrach/kuri.git cd kuri
zig build # build everything zig build test # run 252+ tests
CDP mode — launches Chrome automatically
./zig-out/bin/kuri
Standalone mode — no Chrome needed
./zig-out/bin/kuri-fetch https://example.com
Interactive browser — browse from your terminal
./zig-out/bin/kuri-browse https://example.com
Experimental standalone browser runtime — separate build, not production
(cd kuri-browser && zig build run -- render https://example.com) (cd kuri-browser && zig build run -- bench --offline)
### أول تشغيل، أقصر مسار```bash
# start the server; if CDP_URL is unset, kuri launches managed Chrome for you
./zig-out/bin/kuri
# discover tabs from that managed browser
curl -s http://127.0.0.1:8080/discover
# inspect the discovered tab list
curl -s http://127.0.0.1:8080/tabs
حلقة الوكيل القائمة على الجلسة أولاً
في استخدام HTTP بأسلوب الوكيل، فضّل ترويسة جلسة مع /tab/new و/page/info و/snapshot بدلاً من تكرار tab_id في كل استدعاء.```bash
SESSION=hn-demo
BASE=http://127.0.0.1:8080
curl -s -H "X-Kuri-Session: $SESSION"
"$BASE/tab/new?url=https%3A%2F%2Fnews.ycombinator.com"
curl -s -H "X-Kuri-Session: $SESSION" "$BASE/page/info" SNAP=$(curl -s -H "X-Kuri-Session: $SESSION" "$BASE/snapshot?filter=interactive&format=compact") MORE_REF=$(printf '%s' "$SNAP" | python3 -c 'import re,sys; print(re.search(r""More" @(e\d+)", sys.stdin.read()).group(1))') curl -s -H "X-Kuri-Session: $SESSION" "$BASE/action?action=click&ref=$MORE_REF" curl -s -H "X-Kuri-Session: $SESSION" "$BASE/page/info"
يوجد أيضًا غلافٌ تجريبيٌ رفيعٌ في `tools/kuri_harness.py` إذا أردت أدوات مساعدة بلغة Python فوق نفس واجهة HTTP.
إذا كان متصفح Chrome يعمل لديك بالفعل مع التصحيح عن بُعد، فاضبط `CDP_URL` على إمّا نقطة نهاية WebSocket أو HTTP:```bash
CDP_URL=ws://127.0.0.1:9222/devtools/browser/... ./zig-out/bin/kuri
# or
CDP_URL=http://127.0.0.1:9222 ./zig-out/bin/kuri
تصفح vercel.com في 4 أوامر```bash
1. Discover Chrome tabs
curl -s http://localhost:8080/discover
→ {"discovered":1,"total_tabs":1}
2. Get tab ID
curl -s http://localhost:8080/tabs
→ [{"id":"ABC123","url":"chrome://newtab/","title":"New Tab"}]
3. Navigate
curl -s "http://localhost:8080/navigate?tab_id=ABC123&url=https://vercel.com"
4. Get accessibility snapshot (token-optimized for LLMs)
curl -s "http://localhost:8080/snapshot?tab_id=ABC123&filter=interactive"
→ [{"ref":"e0","role":"link","name":"VercelLogotype"},
{"ref":"e1","role":"button","name":"Ask AI"}, ...]
---
## 🌐 HTTP API
تعيد جميع نقاط النهاية JSON. المصادقة اختيارية عبر متغير البيئة `KURI_SECRET`. **135 نقطة نهاية** — تكافؤ كامل مع agent-browser و browser-use.
### الأساسية
| المسار | الوصف |
|------|-------------|
| `GET /health` | حالة الخادم، عدد التبويبات، الإصدار |
| `GET /tabs` | قائمة بجميع التبويبات المسجّلة |
| `GET /discover` | اكتشاف تلقائي لتبويبات Chrome عبر CDP |
| `GET /tab/current` | الحصول على التبويب الحالي أو تعيينه لجلسة `X-Kuri-Session` |
| `GET /page/info` | URL/العنوان/حالة الجاهزية/منفذ العرض/التمرير المباشر للتبويب النشط |
| `GET /page/state` | ملاحظة مصغّرة للصفحة: url، العنوان، نسبة التمرير، منفذ العرض، عدد النماذج/الروابط/الصور/الحقول |
| `POST /batch` | تنفيذ أوامر متعددة في استدعاء HTTP واحد — يعيد مصفوفة من النتائج |
| `GET /browdie` | 🌰 (بيضة مفاجأة) |
### التحكم في المتصفح
| المسار | المعلمات | الوصف |
|------|--------|-------------|
| `GET /navigate` | `tab_id`, `url` | نقل التبويب إلى URL |
| `GET /tab/new` | `url`, `activate`, `wait` | إنشاء تبويب جديد واختياريًا تفعيله/تعيينه كالتبويب الحالي |
| `GET /tab/close` | `tab_id` | إغلاق تبويب |
| `GET /window/new` | `url`, `activate`, `wait` | إنشاء نافذة/هدف تبويب جديد |
| `GET /snapshot` | `tab_id`, `filter`, `format` | لقطة شجرة A11y مع مراجع `eN`. استخدم `filter=interactive&format=compact` لحلقات الوكيل منخفضة التوكنات. |
| `GET /text` | `tab_id` | استخراج نص الصفحة |
| `GET /screenshot` | `tab_id`, `format`, `quality`, `save` | التقاط لقطة شاشة (base64)؛ عند `save=true` يكتب PNG إلى `STATE_DIR/screenshots` ويعيد `{path,bytes}` بدلاً من ذلك |
| `GET /screenshot/annotated` | `tab_id` | لقطة شاشة مع تسميات عناصر مرقّمة |
| `GET /screenshot/diff` | `tab_id`, `baseline` | فرق بصري بين لقطة الشاشة الحالية ولقطة الأساس |
| `GET /action` | `tab_id`, `ref`, `action`, `value` | نقر/كتابة/تعبئة/تحديد/تمرير/تحويم/نقر مزدوج/تحديد/إلغاء تحديد/إزالة التركيز بالمرجع |
| `GET /evaluate` | `tab_id`, `expression` | تنفيذ JavaScript |
| `GET /evalhandle` | `tab_id`, `expression` | تنفيذ JS، وإرجاع مقبض objectId (وليس القيمة) |
| `GET /close` | `tab_id` | إغلاق التبويب + تنظيف |
| `GET /bringtofront` | `tab_id` | إحضار التبويب إلى المقدمة |
### الإجراءات
| المسار | المعلمات | الوصف |
|------|--------|-------------|
| `GET /clear` | `ref` | مسح قيمة حقل الإدخال |
| `GET /selectall` | `ref` | تحديد كل النص في الإدخال/الحقل القابل للتحرير |
| `GET /setvalue` | `ref`, `value` | تعيين قيمة الإدخال مباشرة (يتجاوز أحداث المفاتيح) |
| `GET /dispatch` | `ref`, `type` | إرسال حدث DOM مخصص على العنصر |
| `GET /boundingbox` | `ref` | الحصول على المستطيل المحيط بالعنصر (x, y, width, height, centerX, centerY) |
| `GET /getattribute` | `ref`, `name` | الحصول على سمة العنصر بالاسم |
| `GET /inputvalue` | `ref` | الحصول على قيمة عنصر الإدخال الحالية |
| `GET /element/state` | `ref`, `check` | قيمة منطقية سريعة: `exists`, `visible`, `enabled`, `checked` |
| `GET /find-element` | `text`/`role`/`label`/`placeholder`/`testid` | محدد دلالي — العثور على عنصر بدون لقطة |
| `GET /highlight` | `ref` أو `selector` | تمييز العنصر بتراكب |
### الماوس واللمس
| المسار | المعلمات | الوصف |
|------|--------|-------------|
| `GET /mouse/move` | `x`, `y` | تحريك الماوس إلى الإحداثيات |
| `GET /mouse/down` | `x`, `y`, `button` | الضغط على زر الماوس |
| `GET /mouse/up` | `x`, `y`, `button` | رفع زر الماوس |
| `GET /mouse/wheel` | `x`, `y`, `deltaX`, `deltaY` | تمرير عجلة الماوس |
| `GET /tap` | `x`, `y` | نقرة لمس (touchStart + touchEnd) |
| `GET /swipe` | `startX`, `startY`, `endX`, `endY` | إيماءة السحب باللمس |
| `GET /drag` | `src_ref`, `tgt_ref` | سحب عنصر إلى الهدف |
### لوحة المفاتيح
| المسار | المعلمات | الوصف |
|------|--------|-------------|
| `GET /keyboard/type` | `tab_id`, `text` | كتابة نص عبر أحداث المفاتيح |
| `GET /keyboard/inserttext` | `tab_id`, `text` | إدراج نص مباشرة |
| `GET /keydown` | `tab_id`, `key` | حدث ضغط مفتاح |
| `GET /keyup` | `tab_id`, `key` | حدث رفع مفتاح |
### استخراج المحتوى
| المسار | الوصف |
|------|-------------|
| `GET /markdown` | تحويل الصفحة إلى Markdown |
| `GET /links` | استخراج جميع الروابط |
| `GET /dom/query` | استعلام محدد CSS |
| `GET /dom/html` | الحصول على HTML للعنصر |
| `GET /dom/attributes` | الحصول على سمات العنصر |
| `GET /pdf` | طباعة الصفحة إلى PDF |
| `GET /find` | بحث نص داخل الصفحة |
### الانتظار
| المسار | المعلمات | الوصف |
|------|--------|-------------|
| `GET /wait` | `selector`, `text`, `url`, `state`, `visible`, `timeout` | انتظار محدد/نص/نمط URL/شبكة خاملة/حالة تحميل |
| `GET /wait/function` | `expression`, `timeout` | انتظار حتى يصبح تعبير JS عشوائي صحيحًا |
| `GET /wait/download` | `timeout` | انتظار اكتمال تنزيل الملف |
### معالجة الحوارات
| المسار | الوصف |
|------|-------------|
| `GET /dialog/auto` | معالجة تلقائية لجميع حوارات JS (قبول أو رفض) |
| `GET /dialog/accept` | قبول الحوار الحالي (مع نص موجه اختياري) |
| `GET /dialog/dismiss` | رفض الحوار الحالي |
### الشبكة وHAR
| المسار | الوصف |
|------|-------------|
| `GET /har/start` | بدء تسجيل حركة الشبكة |
| `GET /har/stop` | إيقاف وإرجاع HAR 1.2 JSON |
| `GET /har/status` | حالة التسجيل + عدد الإدخالات |
| `GET /har/replay` | خريطة API مع مقاطع كود curl/fetch/python |
| `GET /cookies` | الحصول على ملفات تعريف الارتباط |
| `GET /cookies/set` | تعيين ملفات تعريف الارتباط |
| `GET /cookies/delete` | حذف ملفات تعريف الارتباط |
| `GET /cookies/clear` | مسح جميع ملفات تعريف الارتباط |
| `GET /headers` | تعيين ترويسات طلب مخصصة |
| `GET /intercept/start` | بدء اعتراض الطلبات |
| `GET /intercept/stop` | إيقاف اعتراض الطلبات |
| `GET /intercept/requests` | قائمة الطلبات المعترضة |
| `GET /request/detail` | الحصول على نص الاستجابة لمعرف طلب |
| `GET /response/body` | جلب URL وإرجاع نص الاستجابة |
| `GET /network` | إحصائيات حركة الشبكة |
| `GET /download` | تشغيل تنزيل ملف |
### التنقل والحالة
| المسار | الوصف |
|------|-------------|
| `GET /back` | رجوع المتصفح |
| `GET /forward` | تقدم المتصفح |
| `GET /reload` | إعادة تحميل الصفحة |
| `GET /stop` | إيقاف تحميل الصفحة |
| `GET /pushstate` | تنقل SPA عبر history.pushState |
| `GET /storage/local` | الحصول/تعيين localStorage |
| `GET /storage/session` | الحصول/تعيين sessionStorage |
| `GET /storage/local/clear` | مسح localStorage |
| `GET /storage/session/clear` | مسح sessionStorage |
| `GET /session/save` | حفظ جلسة المتصفح |
| `GET /session/load` | استعادة جلسة المتصفح |
| `GET /session/list` | قائمة الجلسات المحفوظة |
| `GET /setcontent` | تعيين HTML الصفحة مباشرة (POST) |
### ملفات تعريف المصادقة
| المسار | الوصف |
|------|-------------|
| `GET /auth/profile/save` | حفظ ملفات تعريف الارتباط + التخزين كملف تعريف مصادقة مسمى |
| `GET /auth/profile/load` | استعادة ملف تعريف مصادقة مسمى إلى تبويب |
| `GET /auth/profile/list` | قائمة ملفات تعريف المصادقة المحفوظة |
| `GET /auth/profile/delete` | حذف ملف تعريف مصادقة محفوظ |
| `GET /auth/extract` | استخراج رموز المصادقة (JWT، ملفات تعريف الارتباط، الترويسات) |
| `GET /set/credentials` | تعيين بيانات اعتماد المصادقة الأساسية HTTP |
على macOS، تُخزَّن أسرار ملفات تعريف المصادقة في سلسلة المفاتيح الخاصة بالمستخدم.
### المحاكاة
| المسار | المعلمات | الوصف |
|------|--------|-------------|
| `GET /emulate` | نوع الجهاز، حجم الشاشة | محاكاة جهاز |
| `GET /set/viewport` | `width`, `height` | تعيين حجم منفذ العرض |
| `GET /set/useragent` | `ua` | تعيين وكيل المستخدم |
| `GET /set/media` | `media` | محاكاة نوع الوسائط |
| `GET /set/offline` | `offline` | تبديل وضع عدم الاتصال |
| `GET /geolocation` | `lat`, `lng` | تجاوز الموقع الجغرافي |
| `GET /timezone` | `timezone` | تجاوز المنطقة الزمنية (مثل `America/New_York`) |
| `GET /locale` | `locale` | تجاوز الإعدادات المحلية (مثل `en-US`) |
| `GET /permissions` | `name`, `state` | منح/رفض الأذونات (الموقع الجغرافي، الإشعارات، الحافظة) |
### السكربتات والحقن
| المسار | الوصف |
|------|-------------|
| `GET /script/inject` | حقن JavaScript في الصفحة (يستمر عبر التنقل) |
| `GET /initscript/remove` | إزالة سكربت تهيئة تم حقنه مسبقًا |
| `GET /addstyle` | حقن ورقة أنماط CSS |
| `GET /expose` | كشف دالة مسماة في سياق JS للصفحة |
### فحص React
| المسار | الوصف |
|------|-------------|
| `GET /react/tree` | شجرة مكونات React عبر خطاف DevTools |
| `GET /react/inspect` | خصائص وحالة مكونات React |
| `GET /react/renders` | تتبع عرض React (بدء/إيقاف) |
| `GET /react/suspense` | حالة حدود React Suspense |
### التسجيل والأداء
| المسار | الوصف |
|------|-------------|
| `GET /recording/start` | تسجيل إجراءات المستخدم (نقر، إدخال، تنقل) |
| `GET /recording/stop` | إيقاف التسجيل + إرجاع سجل الإجراءات |
| `GET /vitals` | مؤشرات Web Vitals الأساسية (LCP, CLS, FID, TTFB, FCP, domInteractive) |
| `GET /perf/lcp` | توقيت Largest Contentful Paint |
| `GET /trace/start` | بدء تتبع الأداء |
| `GET /trace/stop` | إيقاف التتبع |
| `GET /profiler/start` | بدء محلل JS |
| `GET /profiler/stop` | إيقاف المحلل |
### التصحيح
| المسار | الوصف |
|------|-------------|
| `GET /debug/enable` | تفعيل واجهة التصحيح داخل الصفحة ووضع التجميد الاختياري |
| `GET /debug/disable` | تعطيل واجهة التصحيح داخل الصفحة |
| `GET /inspect` | فحص العنصر |
| `GET /errors` | جمع أخطاء JS |
| `GET /console` | قراءة سجلات وحدة التحكم |
| `GET /frames` | قائمة إطارات الصفحة |
| `GET /frame` | التبديل إلى سياق iframe بالاسم أو URL |
| `GET /mainframe` | التبديل مرة أخرى إلى الإطار الرئيسي |
| `GET /diff/snapshot` | فرق مصغّر `+`/`~`/`-` مقابل الاستدعاء السابق لهذا التبويب — حلقة الإجراءات الأكثر كفاءة في التوكنات (باسم مستعار `/snapshot/changes`). يتراجع إلى لقطة كاملة مع ترويسة `! page replaced` عند التغيير الشامل. |
| `GET /diff/url` | مقارنة عنوانَي URL جنبًا إلى جنب (تنقل، لقطة، فرق) |
### البث
| المسار | الوصف |
|------|-------------|
| `GET /screencast/start` | بدء تسجيل الشاشة |
| `GET /screencast/stop` | إيقاف تسجيل الشاشة |
| `GET /video/start` | بدء التقاط الفيديو |
| `GET /video/stop` | إيقاف التقاط الفيديو |
| `GET /ws/start` | بدء نفق WebSocket |
| `GET /ws/stop` | إيقاف نفق WebSocket |
### حلقة مناسبة للوكيل
حلقة الخادم ذات الاحتكاك الأقل هي:
1. `GET /tab/new?url=...`
2. `GET /page/state` (خفيف) أو `GET /snapshot?filter=interactive&format=compact` (كامل)
3. `GET /action?action=click&ref=eN`
4. كرر — أو استخدم `POST /batch` لعمليات متعددة الخطوات في استدعاء واحد
معاملا استعلام `url` و `expression` يتم فك ترميز النسبة المئوية. أرسل `X-Kuri-Session: my-agent` للاحتفاظ بسياق التبويب على جانب الخادم.
---
## 🧠 المهارات
يتضمن المستودع منطقة مهارات قابلة للتوسعة من قبل المستخدم:
- `skills/kuri-skill.md` هي المهارة الأساسية لوكيل Kuri HTTP
- `skills/custom/` محجوزة لمهاراتك الخاصة بالمشروع
- `skills/custom/hackernews-page-2.md` هي مثال ملموس لمهارة مخصصة
- `.claude/skills/kuri-server/SKILL.md` تبقى متزامنة لمهارات المستودع بنمط Claude
تشرح المهارة الأساسية الآن أيضًا مسار المتصفح الذي يجب استخدامه:
- `kuri` HTTP API: أتمتة Chrome/CDP للإنتاج مع الجلسات واللقطات والإجراءات وHAR وملفات تعريف الارتباط ولقطات الشاشة
- `kuri-fetch`: استخراج نصوص/جلب مستقل بدون Chrome
- `kuri-browse`: تصفح تفاعلي في الطرفية
- `kuri-agent`: أتمتة CLI قابلة للبرمجة النصية ضد خادم Kuri
- `kuri-browser/`: بيئة تشغيل متصفح تجريبية منفصلة أصلية بـ Zig لأعمال التكافؤ
بالنسبة لسطر أوامر المتصفح التجريبي:```bash
cd kuri-browser
zig build run -- render https://news.ycombinator.com --selector ".titleline a" --dump text
zig build run -- render https://todomvc.com/examples/react/dist/ --js --wait-eval "document.querySelectorAll('.todo-list li').length >= 1"
zig build run -- parity --offline
zig build run -- bench --offline
zig build run -- serve-cdp --port 9333
kuri-browser serve-cdp يكشف آلية اكتشاف HTTP بأسلوب Chrome بالإضافة إلى موجّه JSON-RPC عبر WebSocket بسيط لاختبارات الدخان للبروتوكول. يعيد التقييم وقت التشغيل كائنات CDP البعيدة ذات الشكل V8 والمدعومة بـ QuickJS؛ وهذا لا يضيف اعتمادًا على V8 وليس توافقًا كاملًا مع Playwright/Puppeteer بعد.
لقطات الشاشة في kuri-browser تُفوَّض حاليًا إلى العارض الرئيسي Kuri/CDP. ابدأ ./zig-out/bin/kuri أولاً، ثم:```bash
cd kuri-browser
zig build run -- screenshot https://example.com --out example.jpg --compress --kuri-base http://127.0.0.1:8080
`--compress` يلتقط خط أساس PNG ومرشح JPEG، ويكتب الملف الأصغر، ويُبلغ عن التوفير بالبايتات. القياس المحلي الحالي على `https://example.com`: `20,523` بايت PNG إلى `18,183` بايت JPEG بجودة 50، مما يوفر `2,340` بايت أو `11%`.
### متقدم
| المسار | الوصف |
|------|-------------|
| `GET /diff/snapshot` | دلتا `+`/`~`/`-` مضغوطة مقارنة باللقطة السابقة (حلقة إجراءات الوكيل) |
| `GET /emulate` | محاكاة الجهاز |
| `GET /geolocation` | تعيين الموقع الجغرافي |
| `POST /upload` | رفع ملف |
| `GET /script/inject` | حقن JavaScript |
| `GET /intercept/start` | بدء اعتراض الطلبات |
| `GET /intercept/stop` | إيقاف الاعتراض |
| `GET /screenshot/annotated` | لقطة شاشة مع تعليقات العناصر |
| `GET /screenshot/diff` | فرق بصري بين لقطات الشاشة |
| `GET /screencast/start` | بدء تسجيل الشاشة |
| `GET /screencast/stop` | إيقاف تسجيل الشاشة |
| `GET /video/start` | بدء تسجيل الفيديو |
| `GET /video/stop` | إيقاف تسجيل الفيديو |
| `GET /console` | الحصول على رسائل الكونسول |
| `GET /stop` | إيقاف تحميل الصفحة |
| `GET /get` | جلب HTTP مباشر (من جانب الخادم) |
| `GET /scrollintoview` | تمرير عنصر مرجعي إلى مجال الرؤية |
| `GET /drag` | سحب من مرجع إلى آخر |
| `GET /keyboard/type` | كتابة نص مع أحداث المفاتيح |
| `GET /keyboard/inserttext` | إدراج نص مباشرة |
| `GET /keydown` | إرسال حدث keydown |
| `GET /keyup` | إرسال حدث keyup |
| `GET /wait` | انتظار حالة الجاهزية أو شروط العنصر |
| `GET /tab/close` | إغلاق تبويب |
| `GET /highlight` | تمييز عنصر بالمرجع أو المحدد |
| `GET /errors` | الحصول على أخطاء الصفحة/وقت التشغيل |
| `GET /set/offline` | تبديل محاكاة الشبكة دون اتصال |
| `GET /set/media` | تعيين ميزات الوسائط المُحاكاة |
| `GET /set/credentials` | تعيين بيانات اعتماد المصادقة الأساسية HTTP |
| `GET /find` | العثور على تطابقات النص في الصفحة الحالية |
| `GET /trace/start` | بدء تتبع Chrome |
| `GET /trace/stop` | إيقاف التتبع وإرجاع بيانات التتبع |
| `GET /profiler/start` | بدء محلل JS |
| `GET /profiler/stop` | إيقاف محلل JS |
| `GET /inspect` | فحص عنصر أو حالة الصفحة |
| `GET /set/viewport` | تعيين حجم منفذ العرض |
| `GET /set/useragent` | تجاوز وكيل المستخدم |
| `GET /dom/attributes` | الحصول على سمات العنصر |
| `GET /frames` | سرد شجرة الإطارات |
| `GET /network` | فحص حالة/طلبات الشبكة |
---
## 🛡️ التخفي وتجنب الروبوتات
تطبق Kuri تصحيحات مكافحة الكشف تلقائيًا عند بدء التشغيل — لا حاجة لإعداد يدوي.
### ما يتم تطبيقه
- **`Page.addScriptToEvaluateOnNewDocument`** — تعمل تصحيحات التخفي قبل أي JS في الصفحة
- **navigator.webdriver = false** — يخفي علامة الأتمتة على مستوى Chromium (`--disable-blink-features=AutomationControlled`)
- **انتحال WebGL/Canvas/AudioContext** — يهزم الكشف القائم على بصمة المتصفح
- **تدوير وكيل المستخدم** — 5 وكلاء مستخدم واقعيون لـ Chrome/Safari/Firefox
- **chrome.csi/chrome.loadTimes** — كعبوات (stubs) لفحوصات Akamai المحددة
### كشف حظر الروبوت
يكتشف الحظر تلقائيًا ويُرجع بديلًا منظمًا:```bash
curl -s "http://localhost:8080/navigate?tab_id=ABC&url=https://protected-site.com"
# If blocked:
# {"blocked":true,"blocker":"akamai","ref_code":"0.7d...",
# "fallback":{"suggestions":["Open URL directly in browser","Use KURI_PROXY"]}}
# If ok: normal CDP response
يكتشف: Akamai، Cloudflare، PerimeterX، DataDome، كابتشا عامة.
دعم الوكيل```bash
KURI_PROXY=socks5://user:pass@residential-proxy:1080 ./zig-out/bin/kuri KURI_PROXY=http://proxy:8080 ./zig-out/bin/kuri
### المواقع المختبرة
| الموقع | الحماية | النتيجة |
|------|-----------|--------|
| Singapore Airlines | Akamai WAF | ✅ تم تجاوزها (كانت محظورة قبل v0.4.0) |
| Shopee SG | حماية مخصصة ضد الاحتيال | ✅ تُحمَّل الصفحة وتعيد التوجيه إلى تسجيل الدخول |
| Google Flights | لا شيء | ✅ تفاعل كامل |
| Booking.com | PerimeterX | ⚠️ يحتاج إلى وكيل |
---
## 🔧 kuri-fetch
جالب HTTP مستقل — لا حاجة إلى Chrome أو Playwright أو npm. يُوزَّع كملف ثنائي بحجم ~2 ميغابايت مع QuickJS مدمج لتنفيذ JavaScript.```bash
zig build fetch # build + run
# Default: convert to Markdown
kuri-fetch https://example.com
# Extract links
kuri-fetch -d links https://news.ycombinator.com
# Structured JSON output
kuri-fetch --json https://example.com
# Execute inline scripts via QuickJS
kuri-fetch --js https://example.com
# Write to file, quiet mode
kuri-fetch -o page.md -q https://example.com
# Pipe-friendly: content → stdout, status → stderr
kuri-fetch -d text https://example.com | wc -w
الميزات
- 5 أوضاع إخراج —
markdown,html,links,text,json - محرك QuickJS للجافاسكربت — ينفّذ
--jsوسوم<script>المضمّنة - بدائل DOM —
document.querySelector,getElementById,window.location,document.title,console.log,setTimeout(بأسلوب SSR) - دفاع SSRF — يحظر عناوين IP الخاصة، ونقاط نهاية البيانات الوصفية، والبروتوكولات غير HTTP
- إخراج ملون — يحترم
NO_COLOR,TERM=dumb,--no-color, وكشف TTY - إخراج إلى ملف —
-o/--outputمع عدد البايتات + ملخص التوقيت - UA مخصص — خيار
--user-agent - الوضع الصامت — يثبّط
-qحالة stderr
🌐 kuri-browse
متصفح طرفية تفاعلي — تصفّح الويب من طرفيتك. لا حاجة إلى Chrome.```bash zig build browse # build + run
kuri-browse https://example.com
### تثبيت سريع (من Github):
```bash
mkdir /path/to/nikto/git/clone
cd /path/to/nikto/git/clone
git clone https://github.com/sullo/nikto.git
إذا كنت تريد أن يستخدم Wireshark هذا، يمكنك
apt update && apt upgrade -y && apt install -y wiresharkإذا لم تكن تملكه بالفعل.``` 🌰 kuri-browse — terminal browser → loading https://example.com
Example Domain
This domain is for use in documentation examples... Learn more [1]
───── Links ───── [1] https://iana.org/domains/example
✓ 528 bytes, 1 links (133ms) [nav] https://example.com> 1 ← type 1 to follow the link
### الأوامر
| الأمر | الإجراء |
|---------|--------|
| `<number>` | اتبع الرابط [N] |
| `<url>` | تنقّل (إذا كان يحتوي على `.`) |
| `:go <url>` | انتقل إلى عنوان URL |
| `:back`, `:b` | الرجوع في سجل التنقل |
| `:forward`, `:f` | التقدم للأمام |
| `:reload`, `:r` | إعادة تحميل الصفحة الحالية |
| `:links`, `:l` | عرض فهرس الروابط |
| `/<term>` | البحث في الصفحة (يظلل التطابقات) |
| `:search <t>` | البحث في الصفحة |
| `:n`, `:next` | إعادة تظليل نتائج البحث |
| `:history` | عرض سجل التنقل |
| `:help`, `:h` | عرض جميع الأوامر |
| `:quit`, `:q` | خروج |
### الميزات
- **عرض Markdown بالألوان** — العناوين والروابط وكتل التعليمات البرمجية والنص العريض والاقتباسات
- **روابط مرقمة** — يحصل كل رابط على `[N]`، اكتب الرقم لاتباعه
- **سجل التنقل** — رجوع/تقدم للأمام مثل المتصفح الحقيقي
- **بحث داخل الصفحة** — `/term` يظلل جميع التطابقات
- **تحليل العناوين النسبية** — يتبع الروابط طبيعيًا عبر الصفحات
- **تصفية ذكية** — يتخطى روابط `javascript:` و `mailto:`
---
## 🤖 kuri-agent
CLI قابل للبرمجة لأتمتة Chrome — يوجّه المتصفح أمرًا بأمر من الطرفية أو سكربتات الصدفة. يشارك حالة الجلسة عبر الاستدعاءات عبر `~/.kuri/session.json`.```bash
zig build agent # build kuri-agent
# 1. Find a Chrome tab
kuri-agent tabs
# → ws://127.0.0.1:9222/devtools/page/ABC123 https://example.com
# 2. Attach to it
kuri-agent use ws://127.0.0.1:9222/devtools/page/ABC123
# 3. Navigate + interact
kuri-agent go https://example.com
kuri-agent snap --interactive # → [{"ref":"e0","role":"link","name":"More info"}]
kuri-agent click e0
kuri-agent shot # saves ~/.kuri/screenshots/<ts>.png
Commands
| Command | Description |
|---|---|
tabs [--port N] | عرض تبويبات Chrome |
use <ws_url> | الارتباط بتبويب (يحفظ الجلسة) |
open [url] [--port N] | فتح تبويب جديد (مع إمكانية الانتقال إلى url) |
status | عرض الجلسة الحالية |
go <url> | الانتقال إلى عنوان URL |
snap [--interactive] [--json] [--text] [--depth N] | لقطة A11y، تحفظ مراجع eN |
click <ref> | النقر على عنصر بواسطة المرجع (أحداث ماوس CDP، متوافق مع React) |
type <ref> <text> | الكتابة داخل عنصر (أحداث مفاتيح لكل حرف، متوافق مع React) |
fill <ref> <text> | ملء قيمة حقل الإدخال |
select <ref> <value> | تحديد خيار من القائمة المنسدلة |
hover <ref> | التحويم فوق عنصر |
focus <ref> | تركيز عنصر |
scroll | تمرير الصفحة |
viewport [width height] | الحصول على أبعاد منفذ العرض أو تعيينها |
eval <js> | تنفيذ JavaScript |
text [selector] | الحصول على نص الصفحة |
shot [--out file.png] | لقطة شاشة |
back | الانتقال للخلف |
forward | الانتقال للأمام |
reload | إعادة تحميل الصفحة الحالية |
cookies | عرض ملفات تعريف الارتباط مع علامات الأمان |
headers | فحص رؤوس استجابة الأمان |
audit | تدقيق أمني شامل |
storage [local|session|all] | تفريغ بيانات localStorage / sessionStorage |
jwt | استخراج وفك ترميز رموز JWT من ملفات تعريف الارتباط والتخزين |
fetch <method> <url> [--data <json>] | طلب fetch مُصادق باستخدام ملفات تعريف ارتباط الصفحة |
probe <url-template> <start> <end> | فحص IDOR: تكرار المعرفات الرقمية في عنوان URL |
grab <ref> | النقر على المرجع، اعتراض window.open، ومتابعة إعادة التوجيه داخل التبويب |
wait-for-tab [--port N] | الاستقصاء عن تبويب جديد، والتبديل التلقائي للجلسة |
stealth | تطبيق تصحيحات مكافحة الكشف |
set-header <name> <value> | إضافة رأس مخصص لجميع الطلبات |
show-headers | عرض الرؤوس الإضافية المخزنة |
clear-headers | إزالة جميع الرؤوس الإضافية |
📱 kuri-mobile (iOS + Android)
واجهة سطر أوامر Zig أصلية للتحكم في محاكيات iOS وأجهزة iPhone الحقيقية (عرض + تشغيل/إنهاء) وأجهزة/محاكيات Android — مستوحاة من mobile-device-mcp، أعيد تنفيذها في Zig بدون Bun/Node/Gradle/Xcode في مسار البناء.```bash
cd kuri-mobile && zig build && cp zig-out/bin/kuri-mobile ../zig-out/bin/
The main kuri binary forwards android/ios subcommands to kuri-mobile:
kuri ios list-devices # sims + real devices (usbmuxd, native) kuri ios openurl https://example.com # navigate Safari kuri ios screenshot out.png # auto-picks booted sim kuri ios launch com.apple.Preferences
kuri android list-devices # native Zig adb wire-protocol client kuri android tap 540 1200 kuri android swipe 100 1500 100 500 kuri android screenshot phone.png kuri android uitree # flat element list via uiautomator dump
**ما هو أصلي بلغة Zig:** بروتوكول مضيف adb (مقابس libc، تأطير سداسي من 4 خانات عبر `host:transport:`/`shell:`/`exec:`)، محلل شجرة واجهة مستخدم XML لنظام Android، عميل plist الخاص بـ usbmuxd `ListDevices`.
**ما يستدعي أوامر خارجية:** `xcrun simctl` (محاكي iOS)، `xcrun devicectl` (تشغيل/إنهاء على أجهزة iOS الحقيقية).
**بدون برنامج تشغيل حسب التصميم:** لا يتم تثبيت أي تطبيق على الجهاز، لذا فإن صناديق `run_code` والنقر/شجرة الواجهة المدعومة بـ XCUITest على أجهزة iOS الحقيقية **غير متاحة** عمداً. راجع [`kuri-mobile/README.md`](https://github.com/justrach/kuri/blob/HEAD/kuri-mobile/README.md) للحصول على مصفوفة التكافؤ الكاملة مقارنةً بالمشروع الأصلي.
---
## 🔒 اختبار الأمان
يدعم `kuri-agent` مسارات أمان أصلية للمتصفح — سجّل الدخول مرة واحدة، ثم نفّذ عمليات الاستطلاع وتدقيق الترويسات وملفات تعريف الارتباط دون مغادرة الطرفية.
### المسارات
**التعداد ← الفحص** — بعد المصادقة، قم بتفريغ ملفات تعريف الارتباط الخاصة بالمصادقة وافحص علامات الأمان:```bash
kuri-agent go https://target.example.com/login
kuri-agent snap --interactive
kuri-agent fill e2 myuser
kuri-agent fill e3 mypassword
kuri-agent click e4 # submit login
kuri-agent cookies
# cookies (3):
# session_id domain=.example.com path=/ [Secure] [HttpOnly] [SameSite=Strict]
# csrf_token domain=.example.com path=/ [Secure] [!HttpOnly]
# tracking domain=.example.com path=/ [!Secure] [!HttpOnly]
تدقيق الترويسات — تحقق من ترويسات الأمان التي يرسلها الهدف:```bash kuri-agent go https://target.example.com kuri-agent headers
→ {"url":"https://...","status":200,"headers":{
"content-security-policy":"default-src 'self'",
"strict-transport-security":"max-age=31536000",
"x-frame-options":"(missing)",
"x-content-type-options":"nosniff", ...}}
**تدقيق شامل** — HTTPS، الترويسات المفقودة، كوكيز مرئية عبر JS في دفعة واحدة:```bash
kuri-agent audit
# → {"protocol":"https:","url":"https://...","score":6,
# "issues":["MISSING:x-frame-options","COOKIES_EXPOSED_TO_JS:2"],
# "headers":{"content-security-policy":"default-src 'self'", ...}}
مسار عبر الحسابات — استخدم eval لإعادة تشغيل استدعاءات API برموز مختلفة:```bash
After login, grab the auth token from localStorage
kuri-agent eval "localStorage.getItem('token')"
Probe a resource ID with the current session
kuri-agent eval "fetch('/api/assessments/42').then(r=>r.status)"
Check for IDOR: does a different user's resource return 200 or 403?
kuri-agent eval "fetch('/api/assessments/99').then(r=>r.status)"
### تنسيق تقرير المسار
يُخرج kuri-agent JSON مناسبًا للتكامل مع خطوط الأنابيب. يُصدر كل أمر أمني سطر JSON واحد — مرِّره عبر `jq` للفرز:```bash
kuri-agent audit | jq '.issues[]'
kuri-agent cookies | head -20
kuri-agent headers | jq '.headers | to_entries[] | select(.value == "(missing)") | .key'
🏗 البنية```
┌──────────────────────────────────────────────────────────┐ │ HTTP API Layer │ │ (std.http.Server, thread-per-connection) │ ├──────────────┬──────────────────┬────────────────────────┤ │ Browser │ Crawler Engine │ kuri-fetch / browse │ │ Bridge │ │ (standalone CLIs) │ ├──────────────┼──────────────────┼────────────────────────┤ │ CDP Client │ URL Validator │ std.http.Client │ │ Tab Registry │ HTML→Markdown │ QuickJS JS Engine │ │ A11y Snapshot│ Link Extractor │ DOM Stubs (Layer 3) │ │ Ref Cache │ Text Extractor │ SSRF Validator │ │ HAR Recorder │ │ Colored Renderer │ │ Stealth JS │ │ History + REPL │ ├──────────────┴──────────────────┴────────────────────────┤ │ Chrome Lifecycle Manager │ │ (launch, health-check, auto-restart, port detection) │ └──────────────────────────────────────────────────────────┘
### Memory Model
- **Arena-per-request** — تُحرَّر كل ذاكرة الطلب في استدعاء `deinit()` واحد
- **No GC** — يكتشف `GeneralPurposeAllocator` في وضع التصحيح كل تسريب
- **سلاسل تنظيف سليمة** — `Launcher → Bridge → CdpClients → HarRecorders → Snapshots → Tabs`
- **حراس `errdefer`** — الأخطاء الجزئية تتراجع بشكل نظيف
### Chrome Lifecycle
| الوضع | السلوك |
|------|----------|
| **Managed** (بدون `CDP_URL`) | يشغّل Chrome headless، ويجد منفذ CDP متاحًا، ويشرف عليه، ويعيد تشغيله تلقائيًا عند الانهيار (بحد أقصى 3 محاولات)، ويقتله عند إيقاف التشغيل |
| **External** (عند ضبط `CDP_URL`) | يتصل بمتصفح Chrome موجود، ويفحص صحته عبر `/json/version`، ولا يقتله عند إيقاف التشغيل |
---
## 📁 البنية```
kuri/
├── build.zig # Build system (Zig 0.16.0)
├── build.zig.zon # Package manifest + QuickJS dep
├── src/
│ ├── main.zig # CDP server entry point
│ ├── fetch_main.zig # kuri-fetch CLI entry point
│ ├── browse_main.zig # kuri-browse CLI entry point
│ ├── js_engine.zig # QuickJS wrapper + DOM stubs
│ ├── bench.zig # Benchmark harness
│ ├── chrome/
│ │ └── launcher.zig # Chrome lifecycle manager
│ ├── server/
│ │ ├── router.zig # HTTP route dispatch (40+ endpoints)
│ │ ├── middleware.zig # Auth (constant-time comparison)
│ │ └── response.zig # JSON response helpers
│ ├── bridge/
│ │ ├── bridge.zig # Central state (tabs, CDP, HAR, snapshots)
│ │ └── config.zig # Env var configuration
│ ├── cdp/
│ │ ├── client.zig # CDP WebSocket client
│ │ ├── websocket.zig # WebSocket frame codec
│ │ ├── protocol.zig # CDP method constants
│ │ ├── actions.zig # High-level CDP actions
│ │ ├── stealth.zig # Bot detection bypass
│ │ └── har.zig # HAR 1.2 recorder
│ ├── snapshot/
│ │ ├── a11y.zig # A11y tree with interactive filter
│ │ ├── diff.zig # Snapshot delta diffing
│ │ └── ref_cache.zig # eN ref → node ID cache
│ ├── crawler/
│ │ ├── validator.zig # SSRF defense, URL validation
│ │ ├── markdown.zig # HTML → Markdown (SIMD tag counting)
│ │ ├── fetcher.zig # Page fetching
│ │ ├── extractor.zig # Readability extraction
│ │ └── pipeline.zig # Parallel crawl pipeline
│ ├── storage/
│ │ ├── local.zig # Local file writer
│ │ └── r2.zig # R2/S3 uploader
│ ├── util/
│ │ └── json.zig # JSON helpers
│ └── test/
│ ├── harness.zig # Test HTTP client
│ ├── integration.zig # Integration tests
│ └── merjs_e2e.zig # E2E tests
├── js/
│ ├── stealth.js # Bot detection bypass
│ └── readability.js # Content extraction
├── kuri-browser/ # Native Zig rendering experiments
└── kuri-mobile/ # iOS + Android device control (Zig-native adb + usbmuxd)
├── src/
│ ├── common/ # io helpers, unified UI tree parser
│ ├── android/ # adb wire protocol client, driver, CLI
│ └── ios/ # simctl, usbmuxd, devicectl, CLI
└── README.md # Full parity matrix vs mobile-device-mcp
⚙️ الإعدادات
| متغير البيئة | الافتراضي | الوصف |
|---|---|---|
HOST | 127.0.0.1 | عنوان ربط الخادم |
PORT | 8080 | منفذ الخادم |
CDP_URL | (none) | الاتصال بمتصفح Chrome موجود (ws://... أو http://127.0.0.1:9222) |
KURI_SECRET | (none) | سر المصادقة لطلبات API |
STATE_DIR | .kuri | دليل حالة الجلسة |
REQUEST_TIMEOUT_MS | 30000 | مهلة طلب HTTP |
NAVIGATE_TIMEOUT_MS | 30000 | مهلة التنقل |
STALE_TAB_INTERVAL_S | 30 | فترة تنظيف التبويبات القديمة |
NO_COLOR | (none) | تعطيل مخرجات CLI الملونة |
💰 تكلفة التوكنات
لمهمة مراقبة من 50 صفحة (من معايير Pinchtab):
| الطريقة | التوكنات | التكلفة ($) | الأفضل لـ |
|---|---|---|---|
/text | ~40,000 | $0.20 | قراءة مكثفة (أرخص بـ13 مرة من لقطات الشاشة) |
/snapshot?filter=interactive&format=compact | ~40,000 | $0.20 | تفاعل عناصر منخفض التوكنات |
/snapshot (full) | ~525,000 | $2.63 | فهم شامل للصفحة |
/screenshot | ~100,000 | $1.00 | التحقق البصري |
🤝 المساهمة
افتح مشكلة قبل إرسال طلب سحب (PR) كبير حتى نتمكن من التوافق على النهج.```bash git clone https://github.com/justrach/kuri.git cd kuri zig build test # 252+ tests must pass zig build test-fetch # kuri-fetch tests (69 tests) zig build test-browse # kuri-browse tests (22 tests)
انظر [CONTRIBUTORS.md](https://github.com/justrach/kuri/blob/HEAD/CONTRIBUTORS.md) للحصول على الإرشادات.
---
## شكر وتقدير
| المشروع | ما استعرناه |
|---------|-----------------|
| [agent-browser](https://github.com/vercel-labs/agent-browser) | نظام مرجع `@eN`، ومقارنة اللقطات، وأنماط تسجيل HAR |
| [Pinchtab](https://github.com/pinchtab/pinchtab) | بنية التحكم بالمتصفح لوكلاء الذكاء الاصطناعي |
| [Pathik](https://github.com/justrach/pathik) | أنماط الزحف عالية الأداء |
| [QuickJS-ng](https://github.com/nicklausw/quickjs-ng) عبر [mitchellh/zig-quickjs-ng](https://github.com/mitchellh/zig-quickjs-ng) | محرك JS لـ `kuri-fetch` |
| [Lightpanda](https://github.com/lightpanda-io/browser) | رائد المتصفحات بدون واجهة رسومية المكتوبة بلغة Zig، وأنماط توافق CDP |
| [Zig 0.16.0](https://ziglang.org) | البنية التقنية بأكملها |
## الترخيص
Apache-2.0