مفتوح المصدر · MIT · MCP

دَع وكيل الذكاء الاصطناعي يصحّح الـ WebView داخل هاتف مستخدمك.

أضف سكربتًا واحدًا إلى صفحة H5 أو إلى WebView تطبيقك. يقرأ المستخدم رمز جهاز قصيرًا، فيستطيع Claude Code أو Codex أو Cursor أو أي عميل MCP أن يرى الصفحة، ويقرأ console والشبكة، وينقر خطوة بخطوة حتى يصل إلى الخلل — والمستخدم يشاهد كل ذلك ويمكنه تولّي التحكم في أي وقت.

  • بلا كابل USB
  • بلا منفذ للتصحيح عن بُعد
  • بلا إعادة بناء للتطبيق، سكربت واحد يكفي
  • يعمل بعد وقوع الخلل

01عرض حيتجربة عملية

خلل حقيقي، يُحَل على هاتف «حقيقي»الآن جرّبه بوكيلك أنت

الهاتف في هذا العرض يشغّل SDK الصفحة نفسه داخل متجر تجريبي. أما بوابته فمحاكاة داخل متصفحك، فلا يغادر أي شيء هذه اللسانة — ومع ذلك فكل لقطة ونقرة وسطر console وإصلاح حي تراه أدناه حقيقي.

هذا حقيقي: بوابة تجريبية عامة على demo.debugger.site، معزولة عن كل شيء آخر وتُمحى كل يوم. والمتجر داخل الهاتف محمَّل من هناك — احصل على مفتاح، ووجّه وكيلك إليه، وشاهده يعمل هنا مباشرة.

جاهز
في انتظار اتصال المتجر…
demo.debugger.site

وكيل الذكاء الاصطناعي

مرتبط بخادم rwd على MCP

شاهد وكيلًا يرتبط بالهاتف، ويعيد إنتاج خلل في صفحة الدفع، ويجد السبب الجذري، ويتحقق من الإصلاح على الفور.

  1. احصل على مفتاح خاص بك

    نقرة واحدة دون تسجيل. يعمل المفتاح على البوابة التجريبية فقط، ويبقى صالحًا حتى تبدأ التجربة من جديد.

    احصل على مفتاح ليُدرَج في الأمر أدناه.

  2. أضف البوابة التجريبية إلى وكيلك

    نفّذ الأمر مرة واحدة في الطرفية، أو أضفه إلى إعدادات عميل MCP لديك. المفتاح مُدرج فيه مسبقًا.

    terminal
    claude mcp add --transport http rwd-demo https://demo.debugger.site/v1/mcp \
      --header "Authorization: Bearer rwd_sk_live_…"
  3. اطلب من وكيلك

    رمز جهاز المتجر الظاهر داخل الهاتف مُدرج في الطلب مسبقًا. وعندما يطلب الوكيل الربط، انقر سماح في المتجر وشاهده يعمل؛ ويمكنك تولّي التحكم أو الإنهاء في أي وقت.

    الطلب
    استخدم خادم MCP المسمّى rwd-demo وارتبط بالجهاز XXXX-XXXX. في المتجر، اختر علبة الهدايا لأحد المنتجات، ثم انتقل إلى الدفع واكتشف سبب ظهور الإجمالي بالشكل «--».

    استبدل XXXX-XXXX بالرمز الظاهر في المتجر.

حدود التجربة

  • مفتاح واحد لكل زائر: لا يصل وكيلك إلا إلى الصفحة التي تعطيه رمزها، وبعد أن تسمح له
  • المستوى interact فقط: بلا سكربتات ولا محتوى طلبات ولا تخزين
  • يحتفظ الوكيل بالصفحة 15 دقيقة كحد أقصى (و5 دقائق عند الخمول)
  • 120 طلب MCP في الدقيقة لكل عنوان IP
  • يُمحى كل يوم الساعة 04:00 (بتوقيت UTC+8) — لا تُدخل بيانات شخصية حقيقية

هاتف العميلK7Q2-9M4X

المتجر التجريبي، مباشرةً····-····

في انتظار اتصال المتجر…

امسح الرمز لفتحه على هاتفك
فتح في لسانة جديدة

هذا هو demo.debugger.site نفسه، يشغّل SDK الحقيقي. ويمكنك مسح الرمز لفتحه على هاتفك.

يعمل كله داخل متصفحك: SDK الحقيقي (sdk.js) في إطار iframe، وطبقة WebSocket وسيطة تنفذ إلى بوابة محاكاة داخل الصفحة، ووكيل مكتوب مسبقًا يرسل استدعاءات RPC حقيقية. رسائل الوكيل تتبع لغة الصفحة، ونتائج الأدوات تظهر بلغة البوابة (الإنجليزية أو الصينية).

02كيف يعمل

ثلاث خطوات من «الصفحة معطّلة على هاتفي» إلى السبب الجذري

  1. أضف SDK الصفحة

    سكربت واحد في <head>، في أبكر موضع ممكن، ليُسجَّل console والشبكة من أول سطر. وداخل التطبيق، احقن السكربت نفسه عند بدء المستند.

  2. يشارك المستخدم رمز الجهاز

    لكل هاتف رمز ثابت مثل K7Q2-9M4X يظهر في شارة صغيرة. ويمكن للمستخدم أن ينقر طلب المساعدة فينتقل الجهاز إلى أعلى قائمة الوكيل.

  3. يرتبط وكيلك عبر MCP

    أضف عنوان MCP المستضاف على البوابة مع مفتاح API، ثم اكتفِ بوصف المشكلة — يجد الوكيل الجهاز، ويطلب الموافقة، ويبدأ العمل.

index.html
<!-- In <head>, before your own scripts; pin a version in production -->
<script src="https://cdn.jsdelivr.net/npm/remote-webview-debugger/dist/sdk.js"></script>
<script>
  RemoteWebviewDebugger.run("https://rwd.example.com/v1", "rwd_pk_…", {
    userId: currentUser?.id ?? null, // optional: find devices by user
    helpButton: true,                // show the “Request assistance” button
  })
</script>

ثبّت إصدارًا محددًا في الإنتاج، أو استخدم نسخة بوابتك نفسها على /v1/sdk.js (مع SRI من لوحة التحكم).

terminal
claude mcp add --transport http rwd https://rwd.example.com/v1/mcp \
  --header "Authorization: Bearer rwd_sk_live_…"
الجهاز K7Q2-9M4X لا يستطيع إتمام الدفع — الإجمالي يظهر بالشكل «--». اكتشف السبب.

03ما يحصل عليه الوكيل

سير عمل DevTools، عبر MCP، على هاتف شخص آخر

  • لقطات إمكانية الوصول

    صيغة YAML على طريقة Playwright مع ref لكل عنصر. يقرأ الوكيل الصفحة كبنية لا كبكسلات — ويعمل على الـ ref.

  • تفاعلات حقيقية

    click وfill وtype وpress وselect وhover وscroll وdrag — مع التحقق من قابلية التعامل مع العنصر، وأحداث يقبلها React وVue.

  • console والشبكة

    تُسجَّل من لحظة تحميل الصفحة في مخازن مؤقتة محدودة الحجم، فتبقى أخطاء ما قبل ارتباط الوكيل موجودة. والمحتوى متاح عند الطلب.

  • جلسات متعددة الصفحات

    القائمة ← التفاصيل ← الدفع، أو WebView ثانٍ: كل صفحات الجهاز تكوّن جلسة واحدة، مع خط زمني يعبر الصفحات.

  • تغييرات الجلسة تُدفَع إليك

    تنتهي كل نتيجة أداة بما تغيّر — صفحة جديدة، أو تنقل، أو خطأ، أو تولّي المستخدم التحكم. بلا استطلاع متكرر.

  • بطاقة مهمة على الهاتف

    يعرض الوكيل خطته وتقدّمه على الجهاز، فيعرف المستخدم دائمًا ما يفعله ولماذا.

  • لقطات الشاشة

    بكسلات أصلية حين يوفّر التطبيق جسرًا لذلك، وإعادة رسم DOM فيما عدا ذلك. والإخفاء يسري على الحالتين.

  • سجل الجلسة على الجهاز

    الصفحات والنقرات وconsole وكل طلب منذ تشغيل التطبيق، محفوظة على الهاتف في IndexedDB — تُقرأ بعد وقوع المشكلة.

  • إصلاحات حية

    في المستوى المتقدّم يستطيع الوكيل تصحيح الصفحة أثناء عملها بـ evaluate_script والتحقق من الإصلاح في الحال.

  • شبكات سيئة

    نبضة خفيفة مع تراجع تدريجي؛ وبعد ثلاث محاولات فاشلة يتحول إلى استطلاع حضور مرة في الدقيقة، وتوقظ البوابة الصفحة عند الحاجة.

  • 11 لغة

    واجهة الهاتف وconsole والنصوص الموجَّهة إلى الوكيل بـ 11 لغة، منها العربية من اليمين إلى اليسار. ويمكنك إضافة حزم لغاتك وصياغتك الخاصة.

  • أي عميل MCP

    Streamable HTTP على /v1/mcp لـ Claude Code وCodex وCursor وغيرها؛ وجسر stdio صغير لكل ما سواها.

كل الأدوات 34

  • list_devices
  • connect_device
  • wait_for_device
  • list_pages
  • select_page
  • wait_for_page
  • take_snapshot
  • find_elements
  • take_screenshot
  • click
  • fill
  • type_text
  • press_key
  • select_option
  • hover
  • scroll
  • drag
  • batch_actions
  • navigate_page
  • go_back
  • reload_page
  • wait_for
  • list_console_messages
  • list_network_requests
  • get_network_request
  • get_storage
  • evaluate_script
  • set_task
  • get_session_timeline
  • get_session_overview
  • get_session_log
  • wait_for_event
  • wait_for_control
  • disconnect_device

04أبرز ما فيه

مصمّم للأخطاء التي لا تقع إلا هناك في الخارج

ثلاثة أشياء لن يمنحها لك كابل، ولا منفذ تصحيح عن بُعد، ولا تسجيل للشاشة.

سجل الجلسة · تخزين بارد على الجهاز

وقع الخلل بالفعل؟ السجل ما زال على الهاتف.

من لحظة تشغيل التطبيق، يكتب SDK سجل جلسة في IndexedDB على الجهاز: الصفحات التي زارها المستخدم، ونقراته وإدخاله، ومخرجات console، وكل طلب — والفاشلة منها مع ترويساتها ومحتواها. لا يُبَث أي شيء إلى أي مكان؛ يبقى على الهاتف وتحت قواعد الإخفاء نفسها، حتى يطلبه وكيل وافق عليه المستخدم بـ get_session_overview وget_session_log. وتُحفظ آخر ثلاث عمليات تشغيل، حتى 10 MB لكل واحدة.

إصلاح حي · evaluate_script

تحقّق من الإصلاح على هاتف العميل، قبل أن تطلق الإصدار.

بموافقة المستخدم على المستوى advanced، يعمل evaluate_script داخل الصفحة — فيستطيع الوكيل تصحيح حالة خاطئة، أو تجاوز دالة، أو إعادة رسم عرض ومشاهدة النتيجة على الجهاز الحقيقي: إصلاح حي يثبت صحة التشخيص. وهو لا يعيش إلا في ذاكرة تلك الصفحة؛ فلا شيء يُحفظ، والنقرات الحساسة تحتاج موافقة المستخدم كما هي.

مبني للوكلاء · MCP

مصنوع للوكلاء، لا لإنسان أمام DevTools.

تنتهي كل نتيجة أداة بما تغيّر على الجهاز منذ الاستدعاء السابق، فلا يحتاج الوكيل إلى استطلاع متكرر. ويُسلَّم محتوى الصفحة كبيانات غير موثوقة. وتعرض بطاقة مهمة على الهاتف خطة الوكيل، وتتحدث البوابة لغة الوكيل — أوصاف الأدوات ونتائجها بـ 11 لغة.

05الخصوصية والتحكم

هاتف المستخدم يبقى هاتف المستخدم

لا ينجح التصحيح عن بُعد إلا إذا وثق به الناس. كل جلسة مرئية، وتحتاج موافقة، ويمكن قطعها في أي لحظة.

  • الموافقة أولًا

    يطلب الوكيل الربط، فيرى المستخدم من يطلب ويختار المستوى على هاتفه. ولا تُحتسب إلا النقرات الحقيقية — فلا يمكن لسكربت أن يوافق على نفسه.

  • تولَّ التحكم أو أنهِ في أي وقت

    أثناء عمل الوكيل تكون الصفحة مقفلة خلف حافة متوهجة. نقرة واحدة على تولّي التحكم توقف الوكيل مؤقتًا، والإنهاء يقطع ارتباطه.

  • الإخفاء افتراضيًا

    كلمات المرور وكل ما يُوسم بـ data-rwd-mask تظهر بالشكل •••• في اللقطات ولقطات الشاشة وconsole وبيانات الشبكة وسجل الجلسة. ويمكنك إضافة محدِّدات وتعبيرات نمطية لكل مشروع.

  • النقرات الحساسة تحتاج موافقة

    وسِم الأزرار بـ data-rwd-confirm («إرسال الطلب»، «حذف الحساب») ليؤكد المستخدم كل نقرة يقوم بها الوكيل عليها.

  • مستويات الوصول

    observe يقرأ، وinteract يعمل على الصفحة، وadvanced يضيف السكربتات ومحتوى الطلبات والتخزين. ويمكن تحديد سقف لكل مفتاح ولكل مشروع.

  • سجل التدقيق

    كل ربط وموافقة واستدعاء RPC وتولٍّ للتحكم يُسجَّل بمن ومتى وماذا — ولا يُسجَّل محتوى الصفحة ولا قيم المعاملات أبدًا.

06التطبيقات الأصلية

داخل تطبيقك، إنه سكربت مستخدم واحد

نزّل SDK مرة واحدة واحقنه عند بدء المستند — WKUserScript على iOS، و addDocumentStartJavaScript على Android. أما صفحات الويب عندك فلا تتغير إطلاقًا.

  • رمز جهاز واحد في كل مكان

    مرّر deviceId ثابتًا (واحفظ deviceToken) ليبقى الرمز نفسه عبر مختلف الـ WebViews والنطاقات.

  • عناصر تحكم أصلية

    اعرض أزرارك الخاصة لتولّي التحكم وإعادته والإنهاء عبر nativeControl()؛ ولا تستطيع سكربتات الصفحة استدعاؤها.

  • نوافذ موافقة أصلية

    nativeApproval: true يسلّم طلبات الربط والتأكيدات إلى واجهة تطبيقك أنت.

  • لقطات ببكسلات حقيقية

    جسر صغير (لقطة WKWebView، أو bitmap على Android) يعطي الوكيل بكسلات حقيقية بدلًا من إعادة رسم DOM.

RemoteDebugger.swift
import WebKit

/// Call before webView.load(…): fetch the SDK once, inject it at document start.
func installRemoteDebugger(into controller: WKUserContentController,
                           userId: String?, done: @escaping () -> Void) {
    let gateway = "https://rwd.example.com/v1"
    URLSession.shared.dataTask(with: URL(string: gateway + "/sdk.js")!) { data, _, _ in
        DispatchQueue.main.async {
            defer { done() }
            guard let data, let sdk = String(data: data, encoding: .utf8) else { return }
            let options: [String: Any] = [
                "deviceId": stableDeviceId, // a UUID kept in UserDefaults
                "userId": userId ?? NSNull(),
                "helpButton": true,
            ]
            let json = String(data: try! JSONSerialization.data(withJSONObject: options), encoding: .utf8)!
            let boot = sdk + "\n;RemoteWebviewDebugger.run(\"\(gateway)\", \"rwd_pk_…\", \(json));"
            controller.addUserScript(WKUserScript(source: boot,
                                                  injectionTime: .atDocumentStart,
                                                  forMainFrameOnly: true))
        }
    }.resume()
}

07استضافة ذاتية

ملف تنفيذي واحد بلغة Go. خوادمك أنت. وبياناتك أنت.

تُضمَّن في البوابة لوحة التحكم و SDK الصفحة. مع SQLite جاهزًا من البداية، و Postgres عند الحاجة، و Docker Compose و Caddy لتأمين HTTPS.

  • لوحة التحكم

    الأجهزة، ومفاتيح API، والأعضاء والأدوار، ودعوات برمز QR، والسياسات، وسجل تدقيق — ودليل تكامل مُعبَّأ بمفاتيحك أنت.

  • التخزين

    ملف SQLite افتراضيًا؛ واضبط RWD_DATABASE_URL=postgres://… لاستخدام Postgres.

  • التشغيل

    مقاييس Prometheus على /v1/metrics، وعناوين SDK مرقَّمة بالإصدار مع SRI، وفحص صحة على /v1/healthz.

دليل النشر

البدء السريع
# حاوية واحدة: لوحة التحكم + البوابة + SDK
docker run -d --name rwd -p 8080:8080 -v rwd-data:/data \
  -e RWD_ADMIN_PASSWORD='change-me' \
  ghcr.io/zanel1u/remote-webview-debugger:latest

# أو ابنِه وانشره وأمِّن HTTPS عبر Caddy
git clone https://github.com/ZaneL1u/remote-webview-debugger
RWD_DOMAIN=rwd.example.com \
  remote-webview-debugger/deploy/platform/deploy.sh you@your-server amd64
# ← لوحة التحكم  https://rwd.example.com
# ← البوابة  https://rwd.example.com/v1  (و MCP على /v1/mcp)

لا يحتاج الخادم إلا إلى Docker؛ أما البناء من المصدر فيحتاج إلى Go و Node.

08الأسئلة الشائعة

أسئلة يطرحها الناس

هل على المستخدم تثبيت أي شيء؟

لا. في صفحات H5 يكون SDK جزءًا من صفحتك، وداخل التطبيق تحقنه من الكود الأصلي. ولا يرى المستخدم إلا شارة صغيرة تحمل رمز جهازه، ونافذة موافقة عندما يطلب وكيل الربط.

ماذا يستطيع الوكيل أن يرى ويفعل؟

لا شيء غير ما وافق عليه المستخدم: صفحات WebView في ذلك الجهاز، وبالمستوى الممنوح. ولا يتحكم أبدًا في أي شيء خارج الـ WebView. تبقى الحقول المخفاة مخفاة، ويُسلَّم محتوى الصفحة إلى النموذج كبيانات غير موثوقة.

وقع الخلل قبل أن يرتبط الوكيل. هل ضاع؟

لا. يحفظ SDK سجل جلسة على الجهاز منذ تشغيل التطبيق — الصفحات والنقرات وconsole والطلبات — فيقرأ الوكيل الذي يرتبط لاحقًا الطريق كاملًا إلى الخلل بـ get_session_log. وفيما عدا ذلك لا يغادر السجل الهاتف أبدًا.

هل يستطيع الوكيل إصلاح الخلل على الهاتف؟

يستطيع التحقق من إصلاح: في المستوى advanced يصحّح evaluate_script الصفحة أثناء عملها في الذاكرة — تصحيح حالة، أو تجاوز دالة، أو إعادة رسم — ويرى الوكيل هل تزول المشكلة. أما الإصلاح الفعلي فيبقى يصل عبر إصدارك المعتاد؛ ولا يُحفظ شيء على الجهاز.

أي الوكلاء يعمل معه؟

أي عميل MCP. يستخدم Claude Code وCodex وCursor عنوان Streamable HTTP المستضاف مباشرةً؛ والعملاء الذين لا يتحدثون إلا stdio يستخدمون rwd mcp، وهو جسر صغير إلى العنوان نفسه.

أي المنصات مدعومة؟

أي WebView أو متصفح حديث على الهاتف: WKWebView على iOS، و Android System WebView، والمتصفحات داخل التطبيقات، و Safari أو Chrome على الهاتف. ومتصفحات سطح المكتب تعمل أيضًا.

وماذا عن الشبكات السيئة أو حجب WebSocket؟

تحتفظ الصفحة بـ WebSocket خفيف للنبضات مع تراجع تدريجي. وإن تعذّر الاتصال ثلاث مرات متتالية، تنتقل إلى استطلاع حضور مرة في الدقيقة، وتوقظها البوابة عندما يريد وكيل الارتباط.

هل يُبطئ صفحتي؟

إنه سكربت واحد. تعيش سجلات console والشبكة في مخازن حلقية محدودة (500 مدخلة لكل منهما، ومحتوى الاستجابات بسقف 5 MB)، ويُكتب سجل الجلسة في الخلفية، والاتصال الخامل لا يتبادل غير النبضات.

هل يعمل جنبًا إلى جنب مع eruda أو vConsole أو PageSpy؟

نعم — تتجاهل اللقطات واختبارات النقر عقدها، ويبقى مرورنا خارج سجلات الشبكة عندها، ويمكنه حتى أن يعمل كعلامة تبويب داخل eruda.

هل العرض أعلاه حقيقي؟

SDK حقيقي وغير معدّل؛ والبوابة وحدها محاكاة داخل متصفحك. تنفذ طبقة WebSocket وسيطة اتصال SDK إليها عبر postMessage، ويرسل وكيل مكتوب مسبقًا نفس استدعاءات RPC التي ترسلها بوابة حقيقية. ولتجربة الشيء الحقيقي من طرف إلى طرف، جرّبه بوكيلك أنت.