وضع الفريق والمجموعات

افتراضيًا، aipager بوت خاص: أنت والبوت في دردشة خاصة واحدة، ولا أحد غيركما. وضع الفريق يفتحه لأشخاص آخرين: مجموعة Telegram يدير فيها عدة مطوّرين الجلسات، أو دردشات خاصة لأشخاص آخرين مع البوت، أو كليهما. لكل دردشة أعضاؤها، ولكل عضو دور يحدد ما يحق له فيها: إرسال الرسائل، أو الرد على أسئلة Claude وطلبات الإذن، أو إدارة الجلسات، أو المشاهدة فقط.

المصدر على GitHub ↖هذه الصفحة مترجمة عن الإنجليزية؛ إذا اختلفت النسختان، فالنسخة الإنجليزية هي الصحيحة. الإنجليزية

افتراضيًا، aipager بوت خاص: أنت والبوت في دردشة خاصة واحدة، ولا أحد غيركما. وضع الفريق يفتحه لأشخاص آخرين: مجموعة Telegram يدير فيها عدة مطوّرين الجلسات، أو دردشات خاصة لأشخاص آخرين مع البوت، أو كليهما. لكل دردشة أعضاؤها، ولكل عضو دور يحدد ما يحق له فيها: إرسال الرسائل، أو الرد على أسئلة Claude وطلبات الإذن، أو إدارة الجلسات، أو المشاهدة فقط.

وضع الفريق اختياري. التثبيت الذي ليس فيه إلا دردشتك الخاصة يعمل كما كان.

القرار بحذر#

إضافة مستخدم Telegram إلى دردشة تعطيه صلاحية تشغيل شيفرة على الكمبيوتر الذي يعمل عليه aipager. بحسب دوره يستطيع:

  • إرسال رسائل يحوّلها Claude إلى أوامر طرفية وتعديلات ملفات واتصالات شبكية؛
  • الرد على طلبات الإذن (سماح / رفض). ما زال ‎~/.claude/settings.json لديك يحدد الأدوات التي يسأل عنها Claude، لكن كل من يسمح له دوره بالموافقة يستطيع الضغط على «السماح»؛
  • بدء الجلسات وإيقافها وإنهاؤها والتنقل بينها.

تُعامل قائمة الأعضاء كما يُعامل الوصول عبر SSH إلى الكمبيوتر. سجل التدقيق (‎~/.claude/aipager-audit.jsonl) يسجّل من فعل ماذا، لكن بعد وقوعه فقط.

الإعداد#

كل شيء يُعدّ بـ aipager config. لا حاجة أبدًا إلى تعديل أي ملف بيدك.

التشغيل الأول (لا إعداد بعد). يسأل معالج الإعداد في أربع خطوات:

  1. توكن البوت؛
  2. دردشتك الخاصة مع البوت (تُكتشف تلقائيًا، أو تُلصق)؛
  3. هل حسابك هو owner (الافتراضي نعم؛ والإجابة بلا تجعلك admin، الذي يُبقي الحد الأدنى للأمان مفعّلًا عليك)؛
  4. يفحص الاعتماديات ويثبّت هوكات Claude Code.

يكتب دردشتك الخاصة كأول دردشة. لا يسأل عن وضع افتراضي: ملخصه يقول «New sessions start in Auto mode; owners and admins can choose Full access in Telegram under /settings → New sessions.» (الجلسات الجديدة تبدأ في الوضع التلقائي؛ والمالكون والمشرفون يستطيعون اختيار الوصول الكامل في Telegram من ‎/settings ← الجلسات الجديدة). ثم يسأل «Connected. Add a team group or other people now?» مع Add a group وAdd a person (DM) وI'm done.

التشغيلات اللاحقة تفتح قائمة التعديل. تعرض الدردشات الموجودة وتقدّم:

  • ‏Add a group scope: مجموعة جديدة، مع أعضائها (أدناه).
  • ‏Add a DM scope: دردشة خاصة لشخص آخر مع البوت. للدردشة الخاصة عضو واحد؛ ويُختار دوره (الافتراضي user؛ ولا يُختار owner إلا لتثبيت لشخص واحد، مثل حاوية صديق خاصة به). لدور ليس فيه can_manage (مثل user) يسأل بعد ذلك عن مجلده الجذر، مملوءًا مسبقًا بالافتراضي (‎~/aipager-users/<label>‎). ولشخص لديه دردشة خاصة مُعدّة من قبل، يقول المعالج ذلك ولا يغيّر شيئًا: يُستخدم Edit a member لتغيير دوره.
  • ‏Edit a scope: للمجموعة، Add a member؛ ولأي دردشة، Rename وEdit scope deny_tools وSet the members' root folder (يُنظر المجلدات الجذرية) وRemove this scope (لا يمكن حذف آخر دردشة). يلزم إنهاء جلسات الدردشة قبل حذفها: جلساتها الجارية تستمر في النشر هناك، ولا تستطيع أي دردشة الوصول إليها من Telegram بعد ذلك (من الكمبيوتر يظل ذلك ممكنًا عبر aipager session ls وaipager session kill <name>‎).
  • ‏Edit a member:‏ Set role وEdit member deny_tools وRemove member (ليس في الدردشة الخاصة، وليس لآخر عضو في مجموعة). للمالك أو المشرف (أو دور لديك فيه bypass_role_denies)، لا يفعل Edit member deny_tools إلا القول إن الأدوات الممنوعة لا تسري على ذلك الدور.
  • ‏Test bot reachability وView policy وRe-install Claude Code hooks وRefresh bot token.

إضافة مجموعة#

  1. إضافة البوت إلى المجموعة، ثم اختيار Add a group scope (أو Add a group في التشغيل الأول).
  2. معرّف المجموعة. اختيار الاكتشاف التلقائي وإرسال ‎/start في المجموعة، أو لصق المعرّف (رقم سالب). يرسل المعالج رسالة اختبار ويسأل هل وصلت. المجموعة المُعدّة من قبل تتوقف هنا مع «This group is already set up. Use Edit a scope → Add a member.» ولا يتغير شيء.
  3. تسمية للمجموعة (تظهر في المعالج وفي Mini App).
  4. أنت أولًا. حين يكون حسابك مالك دردشتك الخاصة، يعرض المعالج إضافتك كأول عضو في المجموعة بالدور owner (الافتراضي نعم؛ ويمكن تخطيه). دون مالك أو مشرف في المجموعة، لا يستطيع أحد هناك استخدام الوصول الكامل أو ‎/settings أو ‎/update.
  5. الأعضاء الآخرون، واحدًا تلو الآخر: طريقة إيجادهم (اكتشاف تلقائي، أو لصق معرّف أو ‎@handle)، وتسمية (تظهر في الدردشة بالشكل ‎@label)، ودور (الافتراضي user). قائمة الأدوار تشمل owner، مع تحذير: المالك يتحكم كليًا في هذا الكمبيوتر، بما في ذلك إعداد aipager وتوكن البوت وبيانات اعتماد Claude. لا يُعطى إلا لك. ويُعطى admin لمن ينبغي أن يستخدموا الوصول الكامل و‎/settings و‎/update في المجموعة. (في دردشته الخاصة مع البوت، يستطيع كل من يحق له إرسال الرسائل والرد على Claude استخدام الوصول الكامل لجلساته، مهما كان دوره.)
  6. قاعدة اختيارية واحدة: "Block file edits (Write, Edit) for user members in this group? Admins and the owner are not affected." (منع تعديل الملفات (Write وEdit) على أعضاء user في هذه المجموعة؟ المشرفون والمالك لا يتأثرون.) الافتراضي لا: فالعضو user لا يكتب أصلًا إلا داخل مجلد مشروع الجلسة. ومع نعم، يُرفض دون سؤال كل Write وEdit في مهمة عضو لا يتجاوز دوره قواعد الأدوار (user وread_only، والأدوار المخصصة دون bypass_role_denies)، وتتوقف المهمة. وعندها يجب أن يرسل ذلك العملَ مشرفٌ أو المالك.
  7. المجلد الجذر للأعضاء، مملوءًا مسبقًا بـ ‎~/aipager-users/group-<label>‎: حيث يبدأ أعضاء user وread_only في المجموعة جلساتهم ويعملون (يُنظر المجلدات الجذرية).

لإضافة شخص إلى مجموعة مُعدّة من قبل: Edit a scope ← المجموعة ← Add a member. كل من في المجموعة يحتفظ بمكانه ودوره.

إيجاد المعرّفات (اكتشاف تلقائي)#

يأخذ الاكتشاف التلقائي لعضو أحدث رسالة من شخص لم يُضف بعد ويسأل «Is this the person to add?» (هل هذا هو الشخص المطلوب إضافته؟) قبل استخدامها (والإجابة بلا تجعله يتخطى ذلك الشخص). ويقترح اسم المستخدم في Telegram تسميةً. في المجموعة، يجب أن يخاطب الشخص البوت: بذكره أو بإرسال ‎/start (يُنظر ما يقرؤه البوت). ويقول المعالج أين يراقب:

  • ‏«Watching through the running daemon» (عبر aipager الجاري): ما دام aipager start يعمل، يستقبل aipager كل رسالة للبوت، لذا يقرأ المعالج ما سجّله aipager في ‎~/.claude/aipager-pending-users.json. يسجّل aipager من يخاطب البوت في مجموعة لا يخدمها بعد (معرّف المجموعة وعنوانها ونوعها، ومعرّف الشخص واسم المستخدم والاسم)، وكل من ليس عضوًا في مجموعة يخدمها. ولا يرد أبدًا في مجموعة لا يخدمها. أما الرسالة الخاصة من شخص غير مُعدّ فيُرد عليها ولا تُسجَّل، لذا لإضافة الدردشة الخاصة لشخص أثناء عمل aipager، يُلصق معرّفه (أو يُوقف aipager أولًا).
  • ‏«Watching Telegram directly» (مباشرة من Telegram): حين يكون aipager متوقفًا، يطلب المعالج بنفسه من Telegram رسائل البوت الأخيرة.

دردشتك الخاصة في التشغيل الأول تُقرأ دائمًا من Telegram. الرسالة من مشرف مجموعة مجهول الهوية، أو المنشورة باسم المجموعة أو باسم قناة، لا تُحسب: معرّف مرسلها (1087968824 أو 136817688 أو 777000) مشترك بين كل من ينشر بهذه الطريقة، لذا يرفضه المعالج، مكتوبًا أو مكتشفًا. يُطلب من الشخص النشر باسمه.

أين يوجد الإعداد#

يكتب المعالج ‎~/.config/aipager/aipager.yaml (الصلاحية 0600): توكن البوت، والدردشات التي يخدمها البوت، وأعضاء كل دردشة مع أدوارهم. ما يحق لكل دور موجود في ‎~/.config/aipager/policy.yaml، وهو ملفك أنت: لا يكتبه المعالج أبدًا (يُنظر كيف تعمل القواعد). التثبيتات المُعدّة بالصيغة القديمة team.yaml تُرحَّل تلقائيًا، بواسطة aipager عند البدء أو بواسطة المعالج في تشغيله التالي.

إعادة التحميل دون إعادة تشغيل#

بعد كل تغيير في الدردشات أو الأعضاء من قائمة التعديل (إضافة مجموعة أو دردشة خاصة أو حذفها، إضافة عضو أو حذفه، ضبط دور، تعديل deny_tools، إعادة تسمية دردشة)، وبعد مجموعة أو شخص أُضيف في نهاية التشغيل الأول أو مجموعة غير مكتملة تُستأنف (إعادة تحميل واحدة لكل ما أُضيف هناك)، يرسل aipager config إلى aipager الجاري إعادة تحميل مباشرة (SIGUSR1) ويقول «Scopes reloaded live (no daemon restart needed)». تعيد إعادة التحميل قراءة aipager.yaml وpolicy.yaml. إذا كان الإعداد على القرص سيُرفض، يقول المعالج «Not applied» مع السبب، ويحتفظ aipager بإعداده السابق حتى إصلاح المشكلة. وإذا لم يستطع المعالج التأكد من أي عملية هي aipager، فإنه يطلب إعادة تشغيله بدلًا من ذلك.

ما تطبّقه إعادة التحميل فورًا:

  • من يحق له استخدام البوت في كل دردشة، وبأي دور وقواعد؛
  • المجموعة أو الدردشة الخاصة الجديدة تبدأ في استقبال الرسائل وتحصل على قائمة / الخاصة بها؛ والمحذوفة تتوقف (تستمر جلساتها في العمل حتى إنهائها)؛
  • الرسالة المحتجزة (التي تنتظر الرد على طلب أو انتهاء مهمة شخص آخر) من شخص لم يعد يحق له الإرسال في تلك الدردشة تُحذف: تحصل على 🤷 ويرد البوت «لم تُرسل إلى Claude: لم يعد مسموحًا لـ ‎@bob بالإرسال هنا.»؛
  • المهمة الجارية لشخص حُذف أو فقد صلاحيات لا تحتفظ إلا بالأشد بين قواعدها القديمة والجديدة (الحد الأدنى المقيد لمن حُذف) لبقية المهمة. والمهمة المكتوبة في الطرفية لا تتغير، ما لم تنضم إليها رسالة Telegram: لا يسجّل aipager لمن هي، لذا تضيق مهمة كهذه حين يفقد أي مالك لتلك الدردشة (أو، في الدردشة الخاصة، عضوها) صلاحيات. والمهمة التي كانت جارية حين أُعيد تشغيل aipager (ما زالت تعمل، أو تنتظر سؤالًا أو إذنًا) تضيق لكل عضو في دردشتها فقد صلاحيات. والترقية لا توسّع أبدًا مهمة جارية: الصلاحيات الجديدة تسري من مهمة ذلك الشخص التالية.

وحده توكن البوت الجديد يحتاج إلى إعادة تشغيل (يقول aipager config ذلك بعد Refresh bot token). وحين لا يعمل aipager، لا تُرسل إعادة تحميل: يقرأ aipager start التالي الإعداد الجديد.

لإعادة التحميل يدويًا (مثلًا بعد تعديل policy.yaml)، تُرسل الإشارة إلى عملية aipager وحدها. تحت خدمة الخلفية:

sh
pid=$(systemctl --user show -p MainPID --value aipager.service)
[ "${pid:-0}" -gt 0 ] && kill -USR1 "$pid"

(الفحص مهم: حين لا تعمل الخدمة، تكون MainPID صفرًا، وkill -USR1 0 يرسل الإشارة إلى عمليات طرفيتك نفسها.)

ولـ aipager الذي بدأته بنفسك بـ aipager start، يُرسل kill -USR1 <pid>‎ إلى تلك العملية. لا تُرسل الإشارة إلى كل نتيجة لـ pgrep -f 'aipager start'‎ (الطرفية أو الحاوية التي تشغّل aipager تطابق أيضًا، وSIGUSR1 يوقف العملية التي لا تتعامل معها)، ولا يُستخدم systemctl --user kill دون ‎--kill-whom=main (جلسات الخدمة تشاركها مجموعتها وستُوقف).

إذا كان aipager.yaml أو policy.yaml تالفًا وقت إعادة التحميل، أو كان aipager.yaml مفقودًا، يكتب aipager تحذيرًا في السجل ويحتفظ بالإعداد السابق في الذاكرة. الخطأ المطبعي أو الملف المنقول جانبًا لا يستطيع إغلاق الباب أمامك ولا إدخال أحد: إعادة التحميل لا تعيد أبدًا aipager له دردشات مضبوطة إلى الوضع الشخصي (إعادة التشغيل وحدها تفعل ذلك).

صلاحيات المشرف للبوت ووضع الخصوصية#

يُجعل البوت مشرفًا في المجموعة، مع صلاحية تثبيت الرسائل. يحتاج إلى ذلك لتثبيت شريط حالة المجموعة (يُنظر ما يراه الجميع). ودونها تعمل المجموعة لكن بلا شريط حالة؛ وإذا أُعطي البوت الصلاحية لاحقًا، يلزم إعادة تشغيل aipager ليظهر الشريط.

البوت الذي هو مشرف في المجموعة يستقبل كل رسالة فيها، مهما كان وضع الخصوصية في BotFather. وهذا آمن: لا يعالج aipager إلا الرسائل المذكورة في ما يقرؤه البوت ويتجاهل الباقي، فلا تصل أحاديث المجموعة إلى أي جلسة. البوت الذي ليس مشرفًا يكون في وضع الخصوصية افتراضيًا (يُترك مفعّلًا)، ولا يمرّر له Telegram عندها إلا بعض رسائل المجموعة؛ وإذا لم تصل إحدى رسائلك، فالحل الرد على إحدى رسائل البوت أو استخدام أمر. إعداد الخصوصية لا يغيّر شيئًا مما يعالجه aipager.

كون الشخص مشرفًا في مجموعة Telegram لا يمنحه شيئًا في aipager. ما يحق لأحد يأتي من دوره في aipager.yaml وحده.

حين يرقّي Telegram المجموعة#

يحوّل Telegram المجموعة العادية إلى supergroup حين تُجعل عامة، أو تُفعّل المواضيع، أو تتجاوز ٢٠٠ عضو، أو تتغير بعض صلاحيات المشرفين، والترقية تعطي المجموعة معرّف دردشة جديدًا. يتبعها aipager وحده: حين يرى الترقية (إشعار Telegram في المجموعة، أو أول نشر إلى المعرّف القديم)، ينقل نطاق المجموعة في aipager.yaml إلى المعرّف الجديد، وينقل معه جلسات المجموعة ووجهات رسائلها و‎/settings الخاصة بها، وينشر سطرًا واحدًا في المجموعة: «رقّى Telegram هذه المجموعة. انتقل aipager معها؛ لا يلزمك فعل شيء.» يبدأ شريط الحالة المثبّت من جديد في المجموعة المرقّاة. وفي سجل aipager تحذير فيه المعرّفان.

أسماء الجلسات داخل aipager تحتفظ بالمعرّف القديم (لا تظهر لك أبدًا)، ويحتفظ aipager.yaml بسجل قصير chat_migrations للنقل، فتبقى الجلسة التي بدأت قبل الترقية تابعة للمجموعة المرقّاة، حتى بعد إعادة التشغيل. الاسم الداخلي لجلسة بالمعرّف القديم (‎/name__g<old id>‎) يعمل في المجموعة المرقّاة ولا يعمل في أي مكان آخر. إذا كان aipager متوقفًا أثناء الترقية، يلاحظها في البدء التالي. المهمة الجارية لحظة الترقية تكتمل وتصل إجابتها إلى المجموعة المرقّاة، لكن بطاقة عملها لا تظهر مجددًا لبقية تلك المهمة. إذا كان المعرّف الجديد نطاقًا مستقلًا من قبل، فلا ينتقل شيء ويذكر السجل ذلك؛ ويُحذف أحد الاثنين بـ aipager config. ويعرض «Test bot reachability» في aipager config المعرّف الجديد حين يصادف مجموعة مرقّاة.

عند كل بدء يبحث aipager عن كل مجموعة مرة واحدة. إذا أجاب Telegram بأن المجموعة غير موجودة أو أن البوت لا يستطيع استخدامها (حُذفت المجموعة، أو أُخرج البوت، أو رُقّيت المجموعة بينما كان aipager متوقفًا ولم يذكر Telegram المعرّف الجديد)، ففي سجل aipager تحذير واحد يذكر النطاق: يلزم التحقق من أن البوت ما زال في المجموعة، وإن كانت قد رُقّيت، تُضاف المجموعة من جديد في aipager config عبر Add a group scope (تحصل على المعرّف الجديد؛ ويُضاف أعضاؤها من جديد)، ثم يُحذف القديم عبر Edit a scope ← Remove this scope (المعرّف القديم لم يعد يعمل). لا ينشر aipager شيئًا ولا يواصل المحاولة.

مواضيع المنتدى غير مدعومة#

مجموعة عادية واحدة (بلا مواضيع) لكل فريق. في مجموعة مفعّل فيها المواضيع، يظل aipager يعمل، لكنه لا يلتزم بموضوع:

  • الرد على أمر أو رسالة (مثل ‎/status، أو الإجابة عن «أي جلسة؟») يبقى في الموضوع الذي أُرسل فيه؛
  • الإشعارات وبطاقات العمل والإجابات وطلبات الإذن وشريط الحالة المثبّت تُنشر في المجموعة دون موضوع، فقد ينتهي بها المطاف في General؛
  • لكل شخص جلسة حالية واحدة للمجموعة كلها، لا واحدة لكل موضوع.

تفعيل المواضيع يرقّي أيضًا المجموعة العادية إلى supergroup، وهو ما يتبعه aipager (أعلاه).

الأدوار#

أربعة أدوار مدمجة (يُنظر aipager/safety.py). الدور المحسوب هو دور الشخص في الدردشة التي يتصرف فيها. لا يستطيع أحد تغيير الأعضاء أو الأدوار من Telegram أو من Mini App: لا يفعل ذلك إلا aipager config على الكمبيوتر، ما يبقيه بيد المالك.

owneradminuserread_only
إرسال الرسائل (can_prompt)✅✅✅❌
الرد على Claude: السماح، الرفض، الأسئلة (can_approve)✅✅✅❌
الإدارة: الوصول الكامل، و‎/settings للمجموعة، و‎/update، وتثبيت ميزة الرسائل الصوتية (can_manage)✅✅❌ (الوصول الكامل: ✅ في دردشته الخاصة)❌
تغيير الأعضاء والأدوار من Telegram أو Mini App❌❌❌❌
تجاوز قواعد منع الأدوار (bypass_role_denies)✅✅❌❌
تجاوز الحد الأدنى للأمان (bypass_safety)✅❌❌❌
Bash وأدوات تشغيل الشيفرة الأخرى✅✅ (قواعد بذل للجهد)❌❌
أي أمر شرطة مائلة✅✅أوامر لوحة «الأوامر» فقط، و‎/compact وتبديلات النموذجمثل user
أين تبدأ الجلسات (‎/new، والاستئناف، وإعادة التشغيل، وتبديل الوضع)في أي مكانفي أي مكانداخل المجلد الجذر للدردشة فقطمثل user
أين تقع كتابة الملفاتفي أي مكانفي أي مكان يسمح به الحد الأدنى للأمانمجلد مشروع الجلسة (حين يكون داخل المجلد الجذر) وscratchpad الخاص به، لا المجلد الرئيسي أبدًامثل user
القراءة في مجلدك الرئيسيفي أي مكان يسمح به الحد الأدنى للأمانفي أي مكان يسمح به الحد الأدنى للأمانداخل المجلد الجذر فقط (المجلدات الأخرى على الكمبيوتر كما كانت، والمجلدات الجذرية لأعضاء آخرين أبدًا)مثل user
ملفات بيانات الاعتماد (‎~/.ssh،‏ ‎~/.git-credentials، ...)مقروءةمقروءةأبدًا (افتراضيًا)أبدًا (افتراضيًا)
Grep/Globفي أي مكانفي أي مكان باستثناء مجلدات aipager المحمية (لا مجلدًا هو أحدها، أو يقع داخل أحدها، أو يحتوي أحدها)مجلد مشروع الجلسة وscratchpad الخاص بهمثل user
  • ‏owner: تحكم كامل، بما في ذلك الحد الأدنى للأمان المدمج. يُفترض أن يكون واحدًا بالضبط: الشخص الذي يدير الكمبيوتر.
  • ‏admin: كل ما يستطيعه المالك في Telegram وMini App: تبديل الجلسات إلى وضع الوصول الكامل (وبدؤها فيه)، واستئناف جلسة في الوصول الكامل، وتغيير ‎/settings للمجموعة، وتشغيل ‎/update، وتثبيت ميزة الرسائل الصوتية، وإرسال أي أمر شرطة مائلة. ويتجاوز المشرف أيضًا قواعد منع الأدوار (deny_tools للنطاق وللعضو لا تسري عليه). يبقى أمران بيد المالك:
    • تغيير الأعضاء والأدوار: لا يفعله إلا aipager config على الكمبيوتر، ولا شيء في Telegram أو Mini App يستطيع ذلك؛
    • تجاوز الحد الأدنى للأمان (إعداد aipager وتوكن البوت، وبيانات اعتماد Claude Code، وملفات تحكم aipager). يستطيع Grep وGlob لدى المشرف البحث في أي مكان آخر، لكن لا في مجلد هو أحد هذه، أو يقع داخل أحدها، أو يحتوي أحدها: يُرفض Grep على ~ أو / أو ‎/tmp (أو دون مجلد من جلسة في المجلد الرئيسي)، وكذلك Glob يبدأ نمطه في أحدها (مثل ‎/home/you/.config/aipager/*‎). الحل البحث داخل مجلد مشروع. في إصدارات Claude Code التي ليس فيها أداة Grep، يبحث Claude عبر Bash؛ وهناك يُرفض أيضًا البحث أو السرد العودي للمجلد الرئيسي كله أو لـ / (grep -rn x ~‎،‏ rg x $HOME،‏ find / -name x)، كبذل للجهد (البحث دون مجلد، أو مع ..، المشغّل من المجلد الرئيسي أو ما تحته لا يُرى)، ولا يُرفض البحث في المشاريع، بما فيه البحث عن مسار المجلد الرئيسي (grep -rn "$HOME" src) (الأمان).

يحتفظ المشرف بـ Bash، ومع الطرفية تكون أنماط الأوامر في الحد الأدنى بذلًا للجهد، لا حدًا: لا يُجعل أحد مشرفًا إلا من يمكن ائتمانه على طرفية في هذا الكمبيوتر.

  • ‏user: قواعد المنع سارية. لا Bash، ولا أي أداة أخرى تشغّل شيفرة (PowerShell وMonitor والرسائل المجدولة وworkflows؛ القائمة هي safety.CODE_EXECUTION_TOOLS)، ولا SendMessage إلى جلسات أخرى، ولا تبديل worktrees. لا تقع كتابة الملفات إلا داخل مجلد الجلسة وscratchpad الخاص بها في Claude Code، وأبدًا في ‎.claude/‎ أو ‎.git/‎ أو ‎.mcp.json داخل المجلد (كل منها يشغّل أوامر). لا يبحث Grep وGlob إلا داخل تلك المجلدات، بأنماط glob نسبية بسيطة. لا يبدأ user الجلسات ولا يستأنفها ولا يعيد تشغيلها ولا يبدّل وضعها إلا داخل المجلد الجذر للدردشة، ولا يقرأ شيئًا في مجلدك الرئيسي خارجه. مجلد الجلسة الذي هو مجلدك الرئيسي، أو /، أو مجلد أعلى منه، أو يقع خارج المجلد الجذر (جلسة بدأت قبل المجلدات الجذرية، أو بدأها شخص آخر)، لا يُحسب: هناك لا يكتب user ولا يبحث إلا في scratchpad. القراءة تتبع قواعد المسارات المحمية، وملفات بيانات اعتمادك غير مقروءة أبدًا: ‎~/.ssh و‎~/.gnupg و‎~/.aws و‎~/.config/gh و‎~/.git-credentials و‎~/.netrc و‎~/.docker/config.json و‎~/.kube و‎~/.config/gcloud و‎~/.azure و‎~/.password-store و‎~/.pgpass و‎~/.npmrc و‎~/.pypirc. أوامر الشرطة المائلة: الموجودة في لوحة «الأوامر» فقط، و‎/compact وتبديلات النموذج (يُنظر بصلاحيات من تعمل الرسالة).
  • ‏read_only: مراقبون. يرون كل شيء في المجموعة، ويستطيعون استخدام ‎/status و‎/diff و‎/whoami و‎/help و‎/start و‎/app، والاطلاع على ‎/settings، وتصفح قائمة ‎/resume فتحها شخص آخر. رسائلهم النصية والصوتية وملفاتهم لا تُرسل إلى أي مكان. أول رسالة يرسلونها في دردشة تتلقى ردًا واحدًا يقول إن دورهم read_only؛ وبعد ذلك يصمت البوت عنهم في تلك الدردشة (لا رد، ولا تفاعل) حتى يُعاد تشغيل aipager. ولهم حدود الأدوات والكتابة نفسها التي لـ user، تحسبًا لوصول إحدى رسائلهم إلى جلسة يومًا ما.

الأدوار المخصصة#

يستطيع policy.yaml تغيير أي حقل في دور مدمج، أو تعريف أدوار جديدة. الحقل الذي يُضبط يحل محل القيمة المدمجة. الحقول:

  • ‏can_prompt،‏ can_approve: إرسال الرسائل؛ والرد على Claude.
  • ‏can_manage: استخدام الوصول الكامل، وتغيير ‎/settings للمجموعة، وتشغيل ‎/update وتثبيت ميزة الرسائل الصوتية (المدمج: owner وadmin قيمتها true، وuser وread_only قيمتها false). لا يسمح أبدًا لأحد بتغيير الأعضاء أو الأدوار، ولا يتجاوز أبدًا الحد الأدنى للأمان.
  • ‏bypass_role_denies،‏ bypass_safety: يُنظر الجدول.
  • ‏deny_tools،‏ allow_tools،‏ deny_bash_patterns،‏ deny_paths_no_access،‏ deny_paths_no_write: يُنظر كيف تعمل القواعد.

الدور المعرَّف من الصفر يبدأ وcan_prompt وcan_approve مفعّلان، وcan_manage والاستثناءان معطّلة، وملفات بيانات الاعتماد في deny_paths_no_access الخاص به، ولا أداة ممنوعة، فلديه Bash حتى يُضبط deny_tools (يحذّر aipager doctor مرة حين يحمله عضو). حصر الكتابة والبحث يسري على كل دور ليس فيه bypass_safety أو bypass_role_denies. والمجلد الجذر يسري على كل دور ليس فيه can_manage، مهما كانت استثناءاته: الدور المخصص الذي فيه bypass_role_denies أو bypass_safety دون can_manage يكتب ويبحث في أي مكان داخل مجلده الجذر (وscratchpad الخاص به) لا في غيرهما، ولا يقرأ شيئًا في مجلدك الرئيسي خارجه (ومع bypass_safety، في جلسة تعمل خارج مجلده الجذر، لا يكتب إلا في scratchpad الخاص به). المالكون والمشرفون وحدهم بلا قيود.

المجلدات الجذرية#

لكل دردشة مجلد جذر للأعضاء: المجلد الذي يبدأ فيه الأعضاء الذين ليس في دورهم هناك can_manage (user وread_only المدمجان، والأدوار المخصصة دونه) جلساتهم ويحتفظون بها. المالكون والمشرفون لا يُحصرون فيه. المجلد الجذر للدردشة الخاصة يخص ذلك الشخص؛ ومجلد المجموعة يتشاركه أعضاؤها المقيدون. لا تتشارك دردشتان مجلدًا واحدًا أبدًا ما لم يُعطَ المجلد نفسه لكلتيهما عن قصد (يطلب المعالج تأكيد ذلك).

  • ضبطه. يسأل عنه aipager config عند إضافة مجموعة، أو دردشة خاصة لدور ليس فيه can_manage، مملوءًا مسبقًا بالافتراضي، ويغيّره Edit a scope ← Set the members' root folder (يُطبَّق فورًا، بإعادة تحميل مباشرة). يعرض الإعداد الحالي المجلد الجذر لكل دردشة، مع ‎(default)‎ حين لا يكون مضبوطًا.
  • الافتراضي هو ‎~/aipager-users/<label>‎ للدردشة الخاصة (تسمية الشخص) و‎~/aipager-users/group-<label>‎ للمجموعة. تُحوَّل التسمية إلى أحرف صغيرة، وكل ما ليس حرفًا أو رقمًا أو . أو _ أو - يصبح -؛ وحين تحصل دردشتان على المجلد نفسه، يُضاف معرّف الدردشة إلى كل منهما (sara-123456). يُنشأ المجلد (و‎~/aipager-users حين يكون جديدًا) بالصلاحية 0700 كي لا يفتحه أحد غيرك، أول مرة يفتح فيها عضو ‎/new أو نموذج «جلسة جديدة» في Mini App. قبل أن تبدأ جلسة فيه، يعلّمه aipager بأنه موثوق لدى Claude Code، حتى لا ينهي سؤال Claude Code «Do you trust this folder?» أول جلسة للعضو. الافتراضي لا يتحرك أبدًا: حين يكون تعديل في aipager config (المجلد الجذر لدردشة أخرى، أو دردشة محذوفة، أو تسمية جديدة) سيغيّر المجلد الافتراضي لدردشة، يكتب المعالج المجلد الذي كان لها مجلدًا جذرًا لها.
  • ما يرفضه المعالج: مسار نسبي، ومحارف البدل، و/، ومجلدك الرئيسي أو مجلد أعلى منه، ومجلد هو أحد مجلدات aipager المحمية أو ملفات بيانات الاعتماد، أو يقع داخل أحدها، أو يحتوي أحدها (‎~/.claude،‏ ‎~/.config/aipager،‏ ‎~/.config،‏ ‎~/.ssh، ...)، والمجلد المؤقت لـ Claude Code (‎/tmp/claude-*‎، حيث يوجد scratchpad كل جلسة). المجلد الذي لم يُنشأ بعد لا بأس به. ويطلب تأكيدًا لمجلد يشغّل نظامك البرامج منه (‎~/bin،‏ ‎~/.local/bin،‏ ‎~/.config/systemd،‏ ‎~/.config/autostart، أو مجلد داخلها).
  • بدء الجلسات. تعرض صفحة المجلد في ‎/new وMini App المجلد الجذر والمجلدات التي داخله مباشرة (لا المخفية، ولا رابطًا يؤدي إلى خارجه)، دون سطر «المجلد الافتراضي»؛ والجلسة الجديدة تبدأ في المجلد الجذر ما لم يُختر أحد تلك المجلدات. وينشئ «مجلد جديد» المجلد داخل المجلد المختار. وكل ما عدا ذلك يحصل على «لا يبدأ دورك الجلسات إلا في مجلدك ~/... أو مجلد داخله.»
  • الجلسات خارجه. استئناف جلسة مجلدها خارج المجلد الجذر، أو إعادة تشغيلها، أو استبدالها، أو تبديل وضعها، يحصل على «تعمل هذه الجلسة خارج مجلدك ~/...، لذا لا يمكن لدورك استئنافها أو إعادة تشغيلها أو تغيير وضعها. يمكنك طلب ذلك من مشرف.» والرسائل إلى جلسة كهذه وهي تعمل تُرسل مع ذلك، ويُخضع هوك الأمان المهمة: لا تكتب هناك إلا في scratchpad.
  • ما يُخضع له الهوك المهمة. مهمة العضو المقيد لا تكتب إلا في مجلد الجلسة (حين يكون داخل المجلد الجذر) وscratchpad الخاص بها، ولا تقرأ ولا تشغّل Grep أو Glob على أي شيء في مجلدك الرئيسي خارج المجلد الجذر (باستثناء scratchpad الخاص بها وملف الرد الخاص بها)، ولا تلمس أبدًا المجلد الجذر لدردشة أخرى، أينما كان. المجلدات خارج مجلدك الرئيسي (‎/usr،‏ ‎/etc، ...) تبقى مقروءة، والمجلدات المحمية تبقى مرفوضة، وBash يبقى ممنوعًا على user. وحين تخلط مهمة عضوين لهما مجلدان جذران مختلفان، يغلب الأضيق؛ والمجلدان اللذان لا يتداخلان لا يتركان إلا مجلد الجلسة نفسه.

لإعادة Bash إلى user (فقط لمن يمكن ائتمانه على طرفية)، يُذكر في allow_tools (الذي يصبح عندها أيضًا قائمة السماح لذلك الدور) أو تُستبدل deny_tools الخاصة به:

yaml
roles:
  user:
    # القائمة المدمجة دون Bash
    deny_tools: [PowerShell, Monitor, REPL, Workflow, CronCreate,
                 RemoteTrigger, AppifactRepl, self_hosted_runner_spawn_local,
                 self_hosted_runner_requeue_session, SendMessage,
                 EnterWorktree, ExitWorktree]

بعدها يحذّر aipager doctor:‏ role user has Bash: its safety rules are best-effort, not a boundary. إذا كان policy.yaml لديك قد ضبط deny_tools لـ user قبل وجود هذا الافتراضي، فقائمتك تظل تحل محله، فيكون لذلك الدور Bash حتى إعادته إلى القائمة؛ وتحذير doctor يخبرك بذلك. يُنظر الأمان ← تطبيق القواعد في وضع الفريق لما لا تغطيه هذه الحدود.

التحدث مع البوت في مجموعة#

ما يقرؤه البوت في المجموعة#

في المجموعة لا يعالج aipager إلا رسالة هي:

  • أمر: ‎/status،‏ ‎/x1 fix the tests، أو الأمر نفسه مع ‎@aipagerbot بعده (‎/x1@aipagerbot)، الذي يضيفه Telegram عند اختياره من القائمة. الأمر الموجّه إلى بوت آخر (‎/x1@otherbot) يُتجاهل؛
  • رد على إحدى رسائل البوت؛
  • رسالة تذكر البوت: ‎@aipagerbot fix the tests؛
  • ضغطة على لوحة مفاتيح البوت في المجموعة. في المجموعة يبدأ كل زر في لوحة المفاتيح بمربع صغير (▫️ إيقاف، ▫️ مسح المحادثة)، ولا يُحسب ضغطةً إلا ذلك النص المعلّم. كتابة الكلمة وحدها حديث عادي: العضو الذي يكتب إيقاف أو مسح المحادثة أو Opus أو اسم جلسة لا يغيّر شيئًا. لاستخدام كلمة لوحة المفاتيح عن قصد دون لوحة المفاتيح، يُخاطب البوت: @aipagerbot إيقاف، أو إيقاف ردًا على إحدى رسائله.

كل ما عدا ذلك (أعضاء يتحدثون فيما بينهم، صورة أو رسالة صوتية ليست ردًا على البوت) لا يحصل على تفاعل ولا رد. وهذا صحيح سواء كان البوت مشرفًا في المجموعة أم لا. الرسائل المعدّلة تُتجاهل في كل مكان: تعديل رسالة لا يفعل شيئًا، والحل إرسالها مرة أخرى.

الصورة أو الملف أو الرسالة الصوتية تعمل بالطريقة نفسها: إرسالها ردًا على البوت، أو ذكر البوت في التعليق. في الألبوم، يوضع التعليق على أول عنصر: عناصر الألبوم التي تصل بعد العنصر الذي فيه التعليق أو الذكر أو الرد تُؤخذ، والتي قبله لا.

الذكر يُحذف. ‎@aipagerbot fix the tests تصل إلى Claude بالشكل fix the tests (كان Claude Code سيقرأ ‎@word على أنه ملف). يعمل ‎@aipagerbot status و‎@aipagerbot x2 مثل كتابة status أو x2 في الدردشة الخاصة، و‎@aipagerbot وحده يعرض أين تذهب رسائلك. أمر الجلسة بعد الذكر يعمل (‎@aipagerbot /x1 fix it)، أما أحد أوامر aipager نفسه فلا: ‎@aipagerbot /stop يحصل على «يمكنك إرسال ‎/stop وحده، دون ذكر البوت.»

الأعضاء فقط. الشخص الذي ليس عضوًا في المجموعة يحصل على رد واحد («🚫 ليس مسموحًا لك باستخدام البوت في هذه الدردشة.») مع معرّفه في Telegram ليعطيه لك، ويُسجَّل من أجل aipager config؛ وبعد ذلك يتجاهله البوت حتى يُعاد تشغيل aipager. والعضو read_only يُخبَر بدوره مرة واحدة (يُنظر الأدوار).

المشرفون المجهولون ينشرون بأسمائهم. مشرف المجموعة الذي فعّل «Remain anonymous»، أو الرسالة المنشورة باسم المجموعة أو باسم قناة، لا يقول من كتب: يعرض Telegram المرسل نفسه لكل مشرف مجهول. لا يستطيع aipager إعطاء رسالة كهذه دور أحد، لذا يجيب «لاستخدام البوت يلزم النشر باسمك الشخصي.» (مرة لكل دردشة حتى يُعاد تشغيل aipager) ولا يفعل شيئًا آخر. لا تُسجَّل أبدًا كمستخدم منتظر، ويرفض المعالج ذلك المعرّف المشترك. الحل إيقاف «Remain anonymous» لحسابك في إعدادات المشرفين في المجموعة، أو النشر من حسابك الشخصي.

التحدث مع جلسة في مجموعة#

الرد على إحدى رسائل جلسة (إجابتها، أو بطاقتها) يرسل رسالتك إلى تلك الجلسة. أو إرسال /x1 رسالتك، أو تعليق يبدأ بـ ‎/x1.

لكل شخص جلسته الحالية الخاصة: آخر جلسة انتقل إليها (‎/x1)، أو أرسل إليها رسالة، أو رد عليها، أو بدأها. إجابة جلسة عضو آخر لا تغيّرها، ولا رسائل الآخرين. الذكر، أو الرسالة الصوتية، أو القالب، أو أمر لوحة المفاتيح يذهب إلى جلستك الحالية، وأمر لوحة المفاتيح أو القالب يسمّيها في رده («🧹 تم إرسال ‎/clear إلى x1»). الأوامر ‎/stop و‎/mode و‎/kill و‎/restart و‎/rename و‎/delete و‎/diff دون اسم لا تعمل إلا على جلستك الحالية (عبر تأكيدها المعتاد)، وفقط حين يناسبها الأمر (تعمل، لـ ‎/stop؛ منتهية، لـ ‎/delete)؛ وإلا فإنها تعرض دائمًا قائمة الاختيار، حتى حين تبقى جلسة واحدة، لأنها قد تخص شخصًا آخر. يعمل ‎/clearqueue و‎/now على جلستك الحالية. و‎/kill x1 والأوامر الأخرى التي فيها اسم تعمل على تلك الجلسة، كما كانت.

  • حين لا تكون لديك جلسة حالية وتعمل أكثر من جلسة، يسأل البوت «أي جلسة؟ يمكنك الرد على إحدى رسائلها، أو إرسال ‎/x1 مع رسالتك.» مع زر لكل جلسة، ولا يرسل شيئًا. وحين تعمل جلسة واحدة فقط، تذهب الرسالة إليها.
  • إذا كانت جلستك الحالية قد انتهت، لا تُرسل الرسالة إلى الجلسة الوحيدة التي ما زالت تعمل (قد تخص شخصًا آخر): يجيب البوت «انتهت x1. أي جلسة؟» مع زر لكل جلسة تعمل، وحين يمكن استئناف x1، «▶️ استئناف x1»، ولا يرسل شيئًا.
  • الضغط على زر جلسة في أي من السؤالين يرسل أيضًا الرسالة التي سأل عنها (نص، أو نص رسالة صوتية، أو ملف) إلى تلك الجلسة، كما لو أُرسلت هناك، ويتغير السؤال إلى «تم الإرسال إلى x2.». لا يستطيع استخدام الأزرار إلا من أرسل الرسالة، ولمدة عشر دقائق فقط وحتى يُعاد تشغيل aipager: بعد ذلك لا يفعل الزر إلا جعل الجلسة جلستك الحالية («هذه الرسالة قديمة جدًا ولم تُرسل؛ يمكنك إرسالها مرة أخرى.»). يعيد ▶️ استئناف الجلسة x1 لكنه لا يرسل شيئًا: يلزم إرسال رسالتك مرة أخرى.
  • الشريط المثبّت ليس فيه سطر «الرسائل تذهب إلى» في المجموعة، لأن ذلك يختلف من شخص إلى آخر.

البطاقات التي تنتظر إجابة تخص كل شخص. بطاقة الجلسة الجديدة تقول «يمكنك الرد على هذه الرسالة باسم الجلسة، ومعه أول مهمة إن رغبت:»، وسؤال إعادة التسمية «يمكنك الرد على هذه الرسالة بالاسم الجديد.». في المجموعة تعرض كل واحدة صاحبها («🆕 جلسة جديدة (‎@alice)»)، ولا يجيب عنها إلا ذلك الشخص، ويستطيع شخصان بدء جلسات أو إعادة تسميتها في الوقت نفسه. رد عضو آخر على بطاقة جلسة جديدة لشخص ما يحصل على «هذه البطاقة تخص ‎@alice. يمكنك إرسال ‎/new للحصول على بطاقتك.» ولا يذهب إلى أي مكان. سؤال إعادة التسمية يتوقف عن الانتظار بعد ١٠ دقائق، أو بمجرد أن يفعل صاحبه شيئًا آخر. بطاقة «x1 جاهزة»، والرد على ‎/x1، و‎/start و‎/help تقول جميعها إن التحدث مع الجلسة يكون بالرد على رسالتها أو بذكر البوت («للتحدث مع x1: الرد على رسالة منها (أو ذكر ‎@aipagerbot).»)، لأن الرسالة العادية لا تصل إلى البوت.

لوحة المفاتيح لكل شخص. القوالب والأوامر والنموذج › و« رجوع لا تغيّر إلا لوحة مفاتيح الشخص الذي يضغطها: يجيب البوت ردًا على ضغطة ذلك الشخص، ولا تتحرك لوحة مفاتيح أحد غيره. « رجوع يصعد من حيث أنت، مهما كان ما يتصفحه الأعضاء الآخرون. لوحة المفاتيح الرئيسية التي يرسلها ‎/start للمجموعة كلها، وتعيد الجميع إلى لوحة المفاتيح الرئيسية. حين تبدأ جلسة للمجموعة أو تنتهي، يرسل aipager لوحة المفاتيح الرئيسية تلك إلى المجموعة مرة أخرى، مرة واحدة، لتبقى أزرار الجلسات فيها محدّثة. بعد الترقية من إصدار ليس فيه الأزرار المعلّمة، قد تُتجاهل ضغطة على زر من لوحة المفاتيح القديمة: يكفي إرسال ‎/start مرة واحدة لإعطاء المجموعة لوحة المفاتيح الجديدة. لوحة مفاتيح الدردشة الخاصة بلا علامة وتعمل كما كانت.

Mini App#

لا يفتح ‎/app تطبيق Mini App إلا في الدردشة الخاصة. في المجموعة لا يظهر في قائمة /؛ وإذا كُتب هناك، يقول للعضو الذي لديه دردشة خاصة مُعدّة مع البوت «📱 يعمل Mini App في الدردشة الخاصة فقط - يمكنك مراسلة البوت مباشرة وإرسال ‎/app هناك.»، ولأي شخص آخر «يُفتح Mini App من دردشتك الخاصة مع البوت. يمكنك أن تطلب من مالك البوت إضافتك.»

يعرض Mini App دردشة واحدة في كل مرة. من ينتمي إلى أكثر من دردشة (مثل دردشته الخاصة ومجموعة) يحصل على صف بأسماء الدردشات في الأعلى للتنقل بينها؛ ويُفتح على دردشته الخاصة، وإلا على أول دردشة تذكره، ويتذكر آخر اختيار على ذلك الهاتف. كل ما فيه (الجلسات، وأزرارها، والإعدادات، والإشعارات التي ينشرها) يخص الدردشة المختارة، بالدور الذي لذلك الشخص فيها. ومع دردشة واحدة لا يظهر شيء إضافي.

بصلاحيات من تعمل الرسالة#

كل رسالة تعمل بـ صلاحيات الشخص الذي أرسلها، في الدردشة التي أرسلها منها. من يكون user في المجموعة وowner في دردشته الخاصة يرسل ويضغط ويشغّل الأوامر في المجموعة بصفة user، مهما كان ترتيب الدردشات في aipager.yaml.

  • كل رسالة Telegram تحمل هوية مرسلها وقواعده إلى الجلسة (يُنظر الأمان ← تطبيق القواعد في وضع الفريق). يرى Claude من أرسل كل رسالة (‎[via Telegram · @bob · role:user]‎ في المجموعة)، لا من أدار الجلسة قبله أبدًا. ومن يرسل رسالة يصبح من يدير الجلسة، سواء كتبها، أو استخدم ‎/x1، أو قالبًا، أو أمرًا من لوحة المفاتيح.
  • الرسائل المحتجزة تحتفظ بمرسلها. ما دامت مهمة شخص آخر جارية (بما في ذلك وكيل في الخلفية بدأته)، أو ما دامت رسالة شخص آخر تنتظر أن تُؤخذ، أو ما دام طلب إذن أو سؤال مفتوحًا، تُحتجز الرسالة الجديدة (👀) وتُرسل حين يزول ذلك، مهمةً مستقلة، بصلاحيات مرسلها هي. المهمة المكتوبة في الطرفية تُحسب للمالك: لا تنضم إليها إلا رسالة المالك (أو، في الدردشة الخاصة، رسالة عضوها). رسائلك لا تنتظر أبدًا مهمتك أنت. وإذا أُوقفت المهمة التي تنتظرها، أو توقفت بسبب أداة ممنوعة، تُحذف الرسائل المحتجزة (🤷): يلزم إرسالها مرة أخرى.
  • الأشد يغلب. إذا انتهت رسائل من أشخاص مختلفين في مهمة واحدة رغم ذلك، تعمل المهمة بأشد مزيج لكل من فيها. والرسالة التي تنضم إلى مهمة جارية لا توسّعها أبدًا: بقية المهمة تحتفظ بأشد قواعد كل من انضم.
  • أوامر الشرطة المائلة من الأدوار المقيدة. الدور الذي لا يتجاوز قواعد الأدوار (user، وread_only، والأدوار المخصصة دون bypass_role_denies، والمرسل الذي لا يعرفه aipager) لا يستطيع إرسال إلا أوامر الشرطة المائلة الموجودة في لوحة «الأوامر» (لوحتك، إن غيّرها keyboard.json)، و‎/compact وتبديلات النموذج (‎/model <name>‎). وكل ما عدا ذلك، سواء كُتب، أو أُرسل بـ ‎/x1 /deliver ...‎، أو كان تعليقًا على ملف، أو أول رسالة لـ ‎/new x1 /review ...‎، أو قالبًا، يحصل على «ذلك الأمر للمشرفين فقط.» مع 🤷، ولا يصل شيء إلى Claude. المالكون والمشرفون يرسلون أي أمر.
  • الأدوار المقيدة تبقى بعيدة عن المجلد الرئيسي وعن ملفات بيانات الاعتماد. مهمة user أو read_only لا تكتب أبدًا في مجلد جلسة هو مجلدك الرئيسي، أو /، أو أعلى منه (بل في scratchpad الخاص بها فقط)، ولا تقرأ أبدًا ملفات بيانات الاعتماد المذكورة في الأدوار.
  • الأدوار المقيدة تبقى في مجلدها الجذر. مهمة دور ليس فيه can_manage لا تقرأ شيئًا في مجلدك الرئيسي خارج المجلد الجذر للدردشة، ولا تكتب شيئًا في مجلد جلسة خارجه. المجلد الجذر هو مجلد الدردشة التي جاءت منها رسالة العضو، أيًّا كانت الجلسة التي تذهب إليها.
  • العضو المحذوف يفقد صلاحياته فورًا، لا مهمته الجارية. المرسل الذي لم يعد aipager يعرفه (حُذف بينما رسالته تنتظر) يعمل بالحد الأدنى المقيد. بعد إعادة تحميل مباشرة تُحذف رسائله المحتجزة، ومهمته الجارية تستمر في العمل، خاضعة للحد الأدنى المقيد حتى تنتهي؛ ويمكن إرسال ‎/stop لإنهائها الآن (يُنظر إعادة التحميل دون إعادة تشغيل).
  • الرسالة من جلسة Claude أخرى تحمل صلاحيات مرسلها. الرسالة التي ترسلها جلسة إلى أخرى (SendMessage في Claude Code) تعمل بصلاحيات المهمة التي أرسلتها، كما تحقق منها aipager، لا بصلاحيات الجلسة المستقبِلة السابقة أبدًا. والرسالة التي لا يستطيع aipager التحقق منها تعمل بأشد القواعد ودون تغيير للملفات ولا وصول إلى الويب (يُنظر الأمان ← الرسائل بين جلسات Claude).
  • الأداة الممنوعة توقف المهمة. حين تحاول مهمة أداة تمنعها قواعدها، تتوقف المهمة فورًا مع «🛑 x1 · منعتها قاعدة الأمان: ... (أُوقفت)»، ويُرفض كل استدعاء أداة لاحق في تلك المهمة أيضًا.

من يستطيع الضغط على ماذا#

كل زر يفحص دور من يضغطه، في الدردشة التي فيها الزر، لحظة الضغط. دور من أرسل الأمر الذي أنشأ الزر لا يُحسب. (بعض البطاقات تفحص أيضًا من طلبها: بطاقات التأكيد وبطاقات ‎/new، أدناه.)

  • الاطلاع متاح لكل عضو (VIEW). يستطيع أعضاء read_only تصفح ‎/resume، وفتح عرض «المنتهية» في ‎/status، وقائمة ⋮ لجلسة، ووضعها أو تغييراتها، وتصفح ‎/settings، وإغلاق قائمة. ولا يستطيعون التصرف: أي زر آخر يجيب «دورك لا يسمح بذلك في هذه الدردشة.»
  • الرد على Claude يحتاج إلى can_approve (APPROVE): السماح، والسماح دائمًا، والرفض، وخيارات السؤال، والإرسال، والمتابعة، وزر الرد في الشريط المثبّت. وهي معطّلة لـ read_only.
  • التصرف في جلسة يحتاج إلى can_prompt (PROMPT): الإيقاف، وإعادة المحاولة، والتلخيص، والإرسال الآن، والإنهاء، وإعادة التشغيل، وإعادة التسمية، والحذف، والاستئناف، وتبديل الوضع، و✍️ التحدث، وإزالة الكل، وإعدادات الجلسة الخاصة، وبطاقات ‎/new. والزر الذي لا يعرفه aipager يحتاج إلى ذلك أيضًا.
  • التبديل إلى الوصول الكامل يحتاج إلى مشرف (MANAGE:‏ owner، أو admin، أو دور فيه can_manage، القاعدة نفسها التي لـ ‎/mode full): «نعم، التبديل» و«إيقاف وتغيير الوضع» على بطاقة تبدّل إلى الوصول الكامل، والاستئناف في الوصول الكامل. التبديل بين «اسأل» والتلقائي متاح لكل من يستطيع التصرف في الجلسة. استئناف جلسة كانت في الوصول الكامل (كتابة ‎/resume x1، أو قائمة الاختيار، أو «استئناف» في بطاقة اسم ‎/new، أو Mini App) يعيدها في الوضع التلقائي لأي شخص آخر، ويذكر الرد ذلك: «♻️ أُعيد فتح x1 في الوضع التلقائي: وضع الوصول الكامل للمشرفين فقط.»
  • في دردشته الخاصة، يستطيع الشخص استخدام الوصول الكامل أيًّا كان دوره (بما في ذلك user؛ لا read_only، الذي لا يرسل رسائل؛ والدور المخصص يحتاج إلى can_prompt وcan_approve، لأن الوصول الكامل يجيب عن كل طلبات الإذن في Claude Code). كل طرق الدخول إلى الوصول الكامل أعلاه تعمل له هناك: ‎/mode full، وبطاقة الوضع، و‎/new !x1، وبطاقات ‎/new، و‎/resume، وMini App. دردشته الخاصة هي الوحيدة التي يسري فيها ذلك: في المجموعة، وفي الدردشة الخاصة لأي شخص آخر، يظل الوصول الكامل يحتاج إلى مشرف. جلساته الجديدة تبدأ في الوضع التلقائي، مثل جلسات الجميع، حتى يختار الوصول الكامل في ‎/settings ← الجلسات الجديدة. ولا شيء آخر مما يفعله المشرف يُفتح له (‎/update، وتثبيت ميزة الرسائل الصوتية، و‎/settings للمجموعة تبقى للمشرفين). منح الوصول الكامل بهذه الطريقة آمن: يبدأ Claude Code مع ‎--dangerously-skip-permissions، الذي لا يتخطى إلا طلبات الإذن الخاصة بـ Claude Code. ويظل هوك PreToolUse في aipager يعمل عند كل استدعاء أداة ويطبّق قواعد دور العضو (الحد الأدنى للأمان، وحصر المجلد، وقواعد المنع، وملفات بيانات الاعتماد) تمامًا كما في وضع «اسأل» والوضع التلقائي.
  • التثبيت يحتاج إلى مشرف (UPDATE): زرا التثبيت وإعادة التشغيل لميزة الرسائل الصوتية، مثل أزرار ‎/update.
  • تغيير ‎/settings للمجموعة يحتاج إلى مشرف. والاطلاع متاح للجميع.
  • بطاقة التأكيد تخص من طلبها. في المجموعة، بطاقات تأكيد الإنهاء (‎/kill، ⋮ إنهاء الجلسة)، وإعادة التشغيل، والحذف، وتبديل الوضع، وقوائم اختيار الجلسات التي يعرضها ‎/kill و‎/restart و‎/delete و‎/mode و‎/stop و‎/rename و‎/diff، وبطاقة «استئناف x1 في:» التي ترسمها ضغطة استئناف (أزرار الوضع فيها) لا تجيب إلا من أرسل الأمر أو ضغط الزر الذي رسمها. ضغطة أي شخص آخر، بما فيها الإلغاء، تحصل على «هذه بطاقة ‎@alice. يمكنك إرسال ‎/kill x2 للحصول على بطاقتك.» (مع أمر تلك البطاقة) ولا تغيّر شيئًا. أما بطاقة ‎/mode نفسها (في أي وضع الجلسة) فهي للجميع: التبديل المضغوط عليها يرسم تأكيدًا يخص من ضغط. وبطاقات ‎/new لا تجيب إلا من أرسل ‎/new. يُتذكَّر صاحب البطاقة حتى تُستخدم أو تُلغى، حتى عبر إعادة تشغيل aipager (أحدث ٤٠٩٦ بطاقة). بطاقة اسم ‎/new وسؤال الاسم في ‎/rename استثناء: تنتهي صلاحيتهما بعد ١٠ دقائق على أي حال، لذا بعد إعادة التشغيل يُرسل الأمر مرة أخرى.
  • الزر لا يعمل إلا في دردشة جلسته. الزر المضغوط في أي مكان آخر يجيب «هذا الزر يخص دردشة أخرى.» ولا يفعل شيئًا، والاستئناف يستأنف دائمًا الجلسة التي يسمّيها الزر، لا جلسة دردشة أخرى بالاسم نفسه أبدًا.
  • الأزرار القديمة لا تغيّر شيئًا. الزر المتبقي من مهمة سابقة، أو من قبل انتهاء الجلسة وعودتها، لا يعمل على ما يجري الآن؛ ويقول ذلك (يُنظر الأوامر ← الأزرار القديمة).

ما يراه الجميع#

الإجابات لـ Claude. كل سماح ورفض وإجابة يُنشر في الدردشة، تحت بطاقة الجلسة، مع من فعله:

text
✅ x1 · مسموح · @alice · Bash: ls -la /tmp
🚫 x1 · مرفوض · @bob · WebFetch: https://example.com
✓ x1 · تمت الإجابة · @carol · Which database? ← Postgres

من غيّر الجلسة. الضغطة على زر لا يراها إلا من يضغط، لذا في المجموعة كل نتيجة تغيّر جلسة تذكر من فعل ذلك:

text
⚠️ x1 · أُوقفت بواسطة @bob
⏹ أُنهيت x2 بواسطة @bob
🔄 أُعيد تشغيل [x1] بواسطة @alice.
🗑️ حُذفت [x3] بواسطة @carol.
⚙️ غُيّر الوضع إلى 🤖 الوضع التلقائي بواسطة @alice.
تم التغيير بواسطة @alice.          (تحت /settings)

تذكر بطاقة «x1 جاهزة» من غيّر وضعها أو نموذجها («غُيّر النموذج إلى Opus بواسطة ‎@bob.»). في الدردشة الخاصة لا تذكر أسطر النتائج هذه أحدًا. والتغيير الذي يُجرى في Mini App يُنشر في الدردشة بالشكل «... عبر Mini App» (والإيقاف منه يذكر أيضًا من فعله على بطاقة الجلسة).

أداة منعتها قاعدة. تتوقف المهمة مع «🛑 x1 · منعتها قاعدة الأمان: Write موجود في deny_tools لهذا الدور (أُوقفت)». إذا طلب Claude Code إذنًا لأداة لا يحق للشخص الذي بدأت رسالته المهمة الجارية استخدامها، يجيب البوت بالرفض بنفسه، ولا يعرض أي طلب، وينشر ⛔ x1 · حُظر Edit على @bob (الدور user) مع ملخص الاستدعاء تحته، مسمّيًا ذلك الشخص. والمهمة التي بدأتها رسائل عدة أشخاص تُمنع إذا كان واحد منهم على الأقل لا يحق له استخدام الأداة، وتسمّيه. والمهمة المكتوبة في الطرفية لك ولا تمنعها قواعد عضو أبدًا، ما لم تنضم إليها رسالة Telegram: عندها تُفحص بقواعد من أرسل آخر رسالة للجلسة (قائمة المجموعة نفسها حين لا يُعرف ذلك). وحين لا يعرف aipager لمن المهمة (كانت جارية حين أُعيد تشغيل aipager)، يستخدم قواعد من أرسل آخر رسالة للجلسة، وقائمة المجموعة نفسها حين لا يُعرف ذلك أيضًا.

حالات الرسائل. 👀 على رسالة تعني أنها أُرسلت إلى الجلسة (أو محتجزة حتى يمكن إرسالها)؛ و👍 تعني أن Claude أخذها؛ و🤷 تعني أنها حُذفت قبل أن يأخذها Claude. يعرض ‎/whoami تسميتك ودورك وقواعدك في هذه الدردشة.

شريط الحالة المثبّت. للمجموعة شريط حالة مثبّت خاص بها (يُنظر الأوامر ← شريط الحالة المثبّت) لا يسرد إلا جلسات هذه المجموعة، إن كان البوت مشرفًا مسموحًا له بالتثبيت. ودون تلك الصلاحية لا يكون للمجموعة شريط: تُحذف الرسالة بدل أن تُترك غير مثبّتة في السجل.

التدقيق على القرص. يسجّل ‎~/.claude/aipager-audit.jsonl كل قرار مع user_id وusername والدردشة، لتمكن لاحقًا إعادة بناء ما فعله كل شخص. ويُكتب دائمًا بالإنجليزية، مهما كانت لغة الدردشة.

اللغة. للمجموعة لغة واحدة لرسائل aipager وبطاقاته ولوحات مفاتيحه، يضبطها مشرف بـ ‎/language؛ وحتى يختار مشرف لغة، تكون الإنجليزية. ولا تتبع أبدًا تطبيق Telegram لأي أحد. ما يراه شخص واحد فقط، الإشعار المنبثق بعد الضغطة، يظهر بلغة ذلك الشخص نفسه: اختياره في دردشته الخاصة مع البوت، وإلا لغة تطبيق Telegram لديه لمن انضم بعد هذا الإصدار، وإلا لغة المجموعة. لا يتغير إلا نص aipager؛ ويجيب Claude كل شخص باللغة التي يكتب بها إليه. يُنظر اللغات.

إلى أين تذهب الرسائل#

  • كل جلسة تخص دردشة واحدة، وكل ما يتعلق بها يذهب إليها: بطاقاتها، وإجاباتها، وطلبات الإذن، والملفات، والإشعارات. الرسالة في دردشة لا تذهب أبدًا إلى جلسة لدردشة أخرى، واسم الجلسة لا يعمل إلا في دردشتها: كتابة اسم جلسة لدردشة أخرى يجيب «لا توجد جلسة بهذا الاسم». الجلسة التي بدأت بينما كان aipager يعمل دون دردشات مُعدّة تحصل على دردشتها بمجرد أن يضيفها aipager config؛ وحتى تحصل الجلسة على دردشة، لا تسردها أي دردشة ولا تستطيع التصرف فيها.
  • الجلسات التي بدأت في الطرفية (aipager session <name>‎) تخص الدردشة الخاصة للمالك: الدردشة الخاصة التي عضوها له الدور owner (دور فيه bypass_safety). ومع عدة دردشات خاصة ليس أي منها للمالك، فهي أول دردشة خاصة في القائمة؛ ودون أي دردشة خاصة، أول دردشة. ولا تذهب أبدًا إلى مجموعة في تثبيت فيه دردشة خاصة.
  • ترقية supergroup تُتبع تلقائيًا (يُنظر حين يرقّي Telegram المجموعة).

بنية aipager.yaml (أجزاء الفريق)#

yaml
schema_version: 3
bot_token: "…"

scopes:
  - kind: dm
    chat_id: 12345       # دردشتك الخاصة: معرّفها هو معرّف المستخدم الخاص بك
    label: owner DM
    members:
      - id: 12345
        label: alice
        role: owner
  - kind: group
    chat_id: -100123456789
    label: team
    deny_tools: [Write, Edit]   # اختياري: الإجابة عن «Block file edits»
    root: /home/alice/aipager-users/group-team   # المجلد الجذر للأعضاء
    members:
      - id: 12345        # معرّف مستخدم Telegram (ليس تسمية، وليس معرّف دردشة)
        label: alice     # كيف يظهر الشخص في الدردشة (@alice)
        role: owner
      - id: 67890
        label: bob
        role: user
        deny_tools: [WebFetch]  # اختياري، لكل عضو
      - id: 11111
        label: charlie
        role: read_only

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

كيف تعمل القواعد#

يعرّف ‎~/.config/aipager/policy.yaml قواعد كل دور. للتحقق منه: aipager policy validate. الحقول المدعومة لكل دور (إلى جانب الحقول في الأدوار المخصصة):

  • ‏deny_tools: أسماء أدوات تُمنع دون سؤال (مثل Write،‏ Edit،‏ Bash،‏ WebFetch).
  • ‏allow_tools: إن لم تكن فارغة، فهي قائمة سماح: كل ما عداها ممنوع على ذلك الدور.
  • ‏deny_bash_patterns: أنماط تُطابَق مع مدخلات Bash.
  • ‏deny_paths_no_access /‏ deny_paths_no_write: قواعد مسارات. لـ user وread_only وكل دور مخصص دون bypass_role_denies، تبدأ deny_paths_no_access بملفات بيانات الاعتماد المذكورة تحت user أعلاه؛ وضبطها يستبدل تلك القائمة، لذا تُنسخ الملفات المراد إبقاؤها إلى قائمتك (والمهمة الجارية التي تنضم إليها رسالة أخرى تخضع للقائمة من جديد حتى تنتهي). القاعدة التي لا تبدأ بـ / أو ~ (‎**/.env) تطابق في أي مكان، لذا ما دامت موجودة يُرفض كل Grep/Glob لدور مقيد (أي بحث قد يقرأ ملفًا كهذا)، وهذا يوقف تلك المهمة.

‏deny_tools للدردشة وdeny_tools للعضو في aipager.yaml تُضاف إلى ما للدور، وallow_tools للعضو تُضاف إلى قائمة سماح الدور. كل ذلك لا يسري إلا على الأدوار التي ليس فيها bypass_role_denies: المالك أو المشرف لا يتأثر بها.

الملفات في ‎~/.config/aipager/policy.d/*.yaml تُقرأ بعد policy.yaml، بترتيب الأسماء، بالصيغة نفسها: حقل الدور المضبوط في ملف لاحق يستبدل القيمة السابقة، وقائمة safety:‎ لا تفعل إلا الإضافة. ويتحقق aipager policy validate منها كلها.

تحت كل الأدوار يوجد الحد الأدنى للأمان (المسارات المحمية وأنماط الأوامر) الذي لا يتجاوزه إلا owner: والمشرفون يخضعون له أيضًا. وهو القائمة المدمجة في aipager مع قسم safety:‎ في policy.yaml، الذي لا يستطيع إلا الإضافة إليه:

yaml
safety:
  deny_paths_no_access: [/srv/secrets/**]   # لا قراءة ولا كتابة ولا بحث
  deny_paths_no_write: [~/notes/**]         # قراءة، دون كتابة
  deny_bash_patterns: ['\bcurl\b']          # أوامر Bash المطلوب منعها

كل مهمة لكل دور ما عدا owner تحصل عليه كاملًا، وكذلك المهام التي لا يستطيع aipager نسبتها إلى أحد؛ ويسرد aipager doctor --safety-check ما هو ساري المفعول. بعد إعادة تحميل مباشرة، يسري التغيير فيه على الرسائل المرسلة بعد إعادة التحميل؛ والمهمة الجارية، أو الرسالة التي تنتظر في قائمة الانتظار، تحتفظ بالقائمة القديمة (إيقاف تلك المهمة يطبّق التغيير فورًا). مسار deny_paths_no_access هناك لا يبدأ بـ / أو ~ يطابق في أي مكان، لذا ما دام موجودًا يُرفض كل Grep/Glob لكل دور ما عدا owner (ويحذّر aipager doctor من ذلك). المسارات المحمية تسري على أدوات الملفات في Claude Code (Read وWrite وEdit وMultiEdit وNotebookEdit وLSP وGrep وGlob)؛ ويجب أيضًا أن يبقى Grep/Glob للدور المقيد داخل مجلد الجلسة (البحث في ‎~/.config عن aipager/**‎ يُرفض). WebFetch لا يُفحص مساره؛ أما SendUserFile (الملفات التي يرسلها Claude إلى الدردشة) فيُفحص مثل Read، ولا يرسل العضو إلا من المجلد الجذر للدردشة (الأمان). مهمة Telegram التي لا يستطيع aipager نسبتها إلى مرسل تحصل على الحد الأدنى، وهو بشدة user على الأقل. وتعمل إعادة المحاولة بصفة من ضغطها إن كان هو من أرسل الرسالة التي تُعاد، وبالحد الأدنى في غير ذلك. أنماط الأوامر لا تهم إلا لدور لديه Bash، وهناك هي مرشّح لا جدار؛ يُنظر الأمان ← تطبيق القواعد في وضع الفريق.

اعتبارات الخصوصية#

  • لا يستمع البوت إلا إلى الدردشات المضبوطة. إضافة البوت إلى مجموعة أخرى لا تفعّله هناك: لا يرد هناك أبدًا. لكنه يسجّل من يخاطبه هناك (المعرّف واسم المستخدم والاسم، ومعرّف المجموعة وعنوانها) في ‎~/.claude/aipager-pending-users.json، ليتمكن aipager config من إضافة تلك المجموعة. لا يقرأ ذلك الملف أحد غيرك، ويحتفظ بأحدث ٢٠٠ شخص ظهروا خلال آخر ٣٠ يومًا.
  • أعضاء read_only يستطيعون قراءة الرسائل والإجابات ومدخلات الأدوات. لا يستطيعون التصرف، لكنهم يرون كل شيء في المجموعة. إذا كان عمل ما يجب أن يبقى مخفيًا عن أحد، فذلك الشخص لا مكان له في المجموعة.
  • في تثبيت فيه دردشة خاصة، لا تظهر جلسات طرفيتك وجلسات دردشتك الخاصة أبدًا في مجموعة (يُنظر إلى أين تذهب الرسائل). جلسة الطرفية التي نقلها aipager أقدم إلى المجموعة تبقى للمجموعة: يلزم إنهاؤها، وحذفها من الجلسات المنتهية للمجموعة، ثم بدؤها من جديد.
  • صلاحية aipager.yaml هي 0600 (للمالك فقط). لا يضبط aipager صلاحية policy.yaml: يلزم إبقاؤه للمالك فقط بنفسك (chmod 600 ~/.config/aipager/policy.yaml).
  • سجل التدقيق (‎~/.claude/aipager-audit.jsonl) ليس له صلاحية خاصة: خصوصيته بقدر خصوصية مجلد ‎~/.claude لديك.

سحب صلاحية مستخدم#

  1. تشغيل aipager config ← Edit a member ← الدردشة ← الشخص ← Remove member. لسحب حقه في إرسال الرسائل مع إبقائه قارئًا، يُستخدم Set role ويُختار read_only بدلًا من ذلك. (لإضافة شخص من جديد لاحقًا: Edit a scope ← المجموعة ← Add a member.) وللدردشة الخاصة لشخص، تُنهى جلساتها، ثم Edit a scope ← دردشته الخاصة ← Remove this scope.
  2. يعيد المعالج تحميل aipager مباشرة؛ ويقول «Scopes reloaded live». فورًا تُحذف رسائله المحتجزة (🤷 ورد «لم تُرسل إلى Claude»)، وتخضع مهمته الجارية للحد الأدنى المقيد حتى تنتهي. ويمكن إرسال ‎/stop لإنهاء تلك المهمة الآن.
  3. إخراجه من مجموعة Telegram أيضًا. ما دام فيها يستطيع قراءة كل ما يُنشر هناك: البطاقات، والإجابات، ومدخلات الأدوات، وطلبات الإذن.

يلزم الانتباه إلى ما يقوله المعالج بعد الخطوة ١. إذا طلب إعادة تشغيل aipager، فهو لم يستطع الوصول إليه: يلزم إعادة تشغيله (aipager service stop، ثم aipager service start)، لأن قائمة الأعضاء السابقة تبقى في الذاكرة حتى ذلك الحين. وإذا قال «Not applied»، فيلزم إصلاح المشكلة التي يذكرها: يحتفظ aipager بالإعداد السابق حتى ذلك الحين. وبعد تعديل aipager.yaml يدويًا، تُرسل إعادة التحميل يدويًا (يُنظر إعادة التحميل دون إعادة تشغيل).