الفكرة بدقيقة: مين بيتصل ومين بيقرّر
Bland (bland.ai) منصة مكالمات صوتية بالذكاء الاصطناعي: بتبعتلها رقم ونص المهمة عبر API، وهي بتتصل وبتحكي وبتسمع وبترجّع لك نص المكالمة. Claude Code بيقدر يستدعي أي API من الطرفية بـ curl. فالفكرة كلها ثلاث قطع:
فيه طريقتين تشغّلها: الـ skill (القسم 3): Claude Code بيستدعيها لما يوصل لقرار، وهي الأبسط وبتكفي أغلب الناس. والـ hook (القسم 5): ربط أوتوماتيكي بنظام الأذونات تبع Claude Code نفسه، فكل مرة بيطلب فيها إذن على أمر خطير بيتصل عليك قبل ما يسألك بالشاشة. ابدأ بالأولى.
التكلفة والحدود بصراحة
- مدفوعة بالدقيقة. صفحة أسعار Bland يوم كتابة الدليل: خطة Start بـ $0.14 للدقيقة بدون رسوم منصة وبدون بطاقة عند التسجيل (وفيها رصيد تجريبي صغير ورقم وارد). السعر بيشمل النموذج والتعرّف على الكلام والصوت؛ الاتصال الهاتفي نفسه (telephony) بينحسب لحاله بسعر التكلفة. مكالمة القرار دقيقة أو دقيقتين، يعني سنتات. الأرقام بتتغيّر: صفحة Pricing هي المرجع.
- المكالمات الدولية (الأردن، السعودية…) بدها رصيد مشترى (الوثائق: 5$ على الأقل أو تفعيل الشحن التلقائي). الرصيد التجريبي ما بيكفي لرقم خارج أمريكا وكندا.
- ما جرّبتها على رقمي لحد كتابة الدليل؛ الريل قال «صار ممكن»، مش «جرّبته». الخطوات من توثيق Bland الرسمي (docs.bland.ai) وطريقة Riley Brown. جرّب المكالمة التجريبية بالقسم 2 قبل ما تعتمد عليها بمهمة حقيقية.
- العربي: Bland بتدعم عدة لغات بحقل
language. جرّب مكالمة بالعربي ومكالمة بالإنجليزي وقارن وضوح الصوت قبل ما تثبّت. - الخصوصية: نص المكالمة بيمرّ على سيرفرات Bland، والتسجيل اختياري (record). لا تخلّي Claude Code يحكي بالمكالمة مفاتيح أو كلمات سر.
شو بتحتاج
- Claude Code شغّال على مشروعك (دليل التركيب).
- حساب Bland ومفتاح API (القسم 1)، ورصيد بيغطّي مكالمات دولية لو رقمك برّا أمريكا.
- رقمك بالصيغة الدولية E.164: +9627XXXXXXXX للأردن، +9665XXXXXXXX للسعودية (بدون صفر البداية وبدون مسافات).
- curl بالطرفية (موجود على ماك ولينكس وويندوز 10+).
مفتاح، مكالمة تجريبية، ملف، وبعدها اتركه يشتغل.
حساب Bland والمفتاح ورقمك
- إنت سجّل على bland.ai (خطة Start بدون بطاقة). من لوحة التحكم انسخ API key.
- إنت لو رقمك خارج أمريكا وكندا: من Billing اشحن 5$ أو فعّل الشحن التلقائي (شرط المكالمات الدولية بالوثائق).
- إنت خزّن المفتاح ورقمك بمتغيّرات بيئة. ما تحطهم بأي ملف جوّا المشروع.
ماك/لينكس (للجلسة الحالية؛ حطهم بملف ~/.zshrc أو ~/.bashrc للدوام):
export BLAND_API_KEY="ضع-المفتاح-هون"
export OWNER_PHONE="+9627XXXXXXXX"ويندوز بـ PowerShell (دائم للمستخدم الحالي):
[Environment]::SetEnvironmentVariable("BLAND_API_KEY", "ضع-المفتاح-هون", "User")
[Environment]::SetEnvironmentVariable("OWNER_PHONE", "+9627XXXXXXXX", "User")افتح طرفية جديدة بعدها عشان المتغيّرات تنقرا، وافتح Claude Code منها.
مكالمة تجريبية من الطرفية (قبل أي skill)
من وثائق Bland: الطلب POST https://api.bland.ai/v1/calls، المصادقة بترويسة authorization: Bearer المفتاح، والحقول المطلوبة phone_number (E.164) وtask (نص المهمة). جرّب على رقمك:
curl -s -X POST https://api.bland.ai/v1/calls \
-H "authorization: Bearer $BLAND_API_KEY" \
-H "content-type: application/json" \
-d '{
"phone_number": "'"$OWNER_PHONE"'",
"task": "You are calling Diyaa on behalf of Claude Code, his coding agent. Say: this is a test call. Ask exactly: shall I continue, yes or no? Wait for a clear yes or no, repeat it back, thank him and end the call.",
"language": "en",
"max_duration": 2,
"wait_for_greeting": true,
"record": false
}'الرد JSON فيه call_id. تلفونك بيرنّ خلال ثواني. جاوب «yes»، وبعد ما تسكّر اقرأ نص المكالمة:
curl -s https://api.bland.ai/v1/calls/ضع-call_id-هون -H "authorization: Bearer $BLAND_API_KEY"بالرد: completed (true لما تخلص)، وconcatenated_transcript (نص المكالمة كامل)، وtranscripts (سطر سطر، مين حكى). هاد النص هو اللي Claude Code رح يقرأه ويقرّر منه. بدك المكالمة بالعربي؟ غيّر "language": "ar" واكتب نص المهمة بالعربي، وقارن.
على ويندوز PowerShell، نفس الطلب بـ Invoke-RestMethod أو شغّل الأمر فوق من Git Bash. ولو ما رنّ: راجع الرصيد (دولي) وصيغة الرقم.
الـ skill: ملف call-me كامل
الصق الملف بـ .claude/skills/call-me/SKILL.md جوّا مشروعك (أو ~/.claude/skills/call-me/SKILL.md لكل مشاريعك). أول جزء بالعربي عشان Claude Code يعرف إمتى يستعمله، والتعليمات بالإنجليزي. $ARGUMENTS = السؤال لو كتبته إنت بعد الأمر (من وثائق Claude Code)، وallowed-tools بتسمح بـ curl وsleep بدون سؤال بدور الاستدعاء.
---
name: call-me
description: اتصل على تلفوني لما تحتاج قرار أو موافقة مني (حذف، نشر، دفع، أي شي ما بينرجع)، اسمع الجواب وكمّل عليه. استعمله لما أقول «اتصل عليّ» أو «خذ موافقتي بالتلفون»، أو لما توصل لخطوة ما بتنرجع وأنا مش قدام الشاشة.
argument-hint: [question]
allowed-tools: Bash(curl *) Bash(sleep *)
---
# call-me — phone the owner for a decision
Question to ask, if the user gave one: $ARGUMENTS
If no question was given, you reached a step that needs the owner's approval (deleting, publishing, paying, anything irreversible): write a one-paragraph summary of the situation and ONE exact yes/no question yourself. Keep both short enough to say on the phone in 20 seconds. Never mention keys, passwords or file contents.
## 1. Place the call
The API key is in the environment variable BLAND_API_KEY and the number in OWNER_PHONE (E.164). Never print either.
curl -s -X POST https://api.bland.ai/v1/calls \
-H "authorization: Bearer $BLAND_API_KEY" -H "content-type: application/json" \
-d '{"phone_number":"'"$OWNER_PHONE"'","task":"You are calling Diyaa on behalf of Claude Code, his coding agent. Say: <summary>. Then ask exactly: <question> Wait for a clear yes or no, repeat it back, thank him and end the call.","language":"en","max_duration":3,"wait_for_greeting":true,"record":false}'
Read `call_id` from the JSON reply. If the reply has "status":"error", stop and show the message to the user.
## 2. Wait for the answer
Every 20 seconds (`sleep 20`) run:
curl -s https://api.bland.ai/v1/calls/<call_id> -H "authorization: Bearer $BLAND_API_KEY"
until the JSON has "completed": true. Give up after 10 minutes (no answer = not approved).
## 3. Decide
Read `concatenated_transcript`. Approved ONLY if the owner's words contain a clear yes («yes», «كمّل», «موافق», «اه كمل»). «no», «لا», silence, a question back, or anything unclear = NOT approved.
## 4. Continue
- Approved: do the step, then say in the chat: «📞 approved by phone (call <call_id>): <question>».
- Not approved: do NOT do the step; say what was asked and that it was declined, and wait for the user in the chat.
## Rules
- Call OWNER_PHONE only, never any other number.
- One call at a time; never retry a call that connected.
- One question per call. If two decisions are pending, ask the first, continue, and call again later.ليش language en افتراضياً؟ لأنه أوضح بالتجربة الصوتية عند أغلب المنصات. لو العربي زبط معك بالقسم 2، غيّرها لـ ar واكتب جملة الافتتاح بالعربي جوّا task.
خلّي Claude Code يستعملها لحاله
بأول المهمة الطويلة، سطر واحد بالطلب:
نظّف مجلد المشروع من الملفات المؤقتة، حدّث الحزم، وشغّل الاختبارات. أنا طالع: لما تحتاج موافقتي على أي حذف أو تعديل ما بينرجع، استعمل skill call-me واسألني بالتلفون. بدون موافقة بالتلفون لا تحذف شي.أو استدعيها إنت مباشرة بسؤال محدّد:
/call-me Shall I deploy version 2.3 to production now?عشان تصير القاعدة دائمة بهالمشروع (بدون ما تكرّرها كل مرة)، سطر بملف CLAUDE.md:
## Decisions
Before any irreversible step (delete, publish, deploy, payment) when the user is not answering in the chat within a minute, use the call-me skill and act only on a phone "yes".شو بيصير عملياً: Claude Code بيشتغل، بيوصل لـ «أحذف 40 ملف؟»، بيستدعي السكيل، تلفونك بيرنّ: «مرحبا، أنا بتصل عن Claude Code. لقيت 40 ملف مؤقت بمجلد build، أحذفهم؟ نعم أو لا». بتقول «كمّل»، بيكرّرها، بيسكّر، وبيحذف. وبالشات بيكتب لك سطر «📞 approved by phone». ملف CLAUDE.md وإعدادات الأمان بيكمّلوا الصورة.
الطريقة الأوتوماتيكية: hook على طلبات الإذن
للي بيعرف شوي برمجة. Claude Code نفسه بيطلب إذن قبل الأوامر الخطيرة، وفيه hooks: سكربتات بتشتغل عند أحداث معيّنة. حدث PermissionRequest بيشتغل لما Claude Code بده إذن، والسكربت بيقدر يرجّع قرار «اسمح» أو «ارفض» بصيغة JSON (من وثائق Claude Code). يعني: السكربت بيتصل عليك عبر Bland، بيقرأ جوابك، وبيرجّع القرار لـ Claude Code بدون ما يسألك بالشاشة.
بملف .claude/settings.json بالمشروع (أو ~/.claude/settings.json):
{
"hooks": {
"PermissionRequest": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": "node \"$CLAUDE_PROJECT_DIR/.claude/hooks/call-me.mjs\"", "timeout": 600 }
]
}
]
}
}السكربت .claude/hooks/call-me.mjs (بيقرأ تفاصيل الطلب من stdin، بيتصل، وبيرجّع القرار):
import { readFileSync } from 'node:fs';
const input = JSON.parse(readFileSync(0, 'utf8')); // { tool_name, tool_input, ... }
const cmd = String(input.tool_input?.command ?? '').slice(0, 200);
const H = { authorization: `Bearer ${process.env.BLAND_API_KEY}`, 'content-type': 'application/json' };
const task = `You are calling Diyaa on behalf of Claude Code. It wants to run this command: ${cmd}. Ask exactly: allow it, yes or no? Wait for a clear yes or no, repeat it back and end the call.`;
const r = await fetch('https://api.bland.ai/v1/calls', { method: 'POST', headers: H, body: JSON.stringify({ phone_number: process.env.OWNER_PHONE, task, max_duration: 3, wait_for_greeting: true }) });
const { call_id } = await r.json();
let text = '';
for (let i = 0; i < 30; i++) { // up to 10 minutes
await new Promise((ok) => setTimeout(ok, 20000));
const c = await (await fetch(`https://api.bland.ai/v1/calls/${call_id}`, { headers: H })).json();
if (c.completed) { text = String(c.concatenated_transcript ?? ''); break; }
}
const yes = /\b(yes|yeah)\b|كمّل|كمل|موافق|اه\s*كمل/i.test(text) && !/\b(no|don't|do not)\b|لا\s/i.test(text);
const decision = yes ? { behavior: 'allow' } : { behavior: 'deny', message: `Declined by phone (call ${call_id}).` };
process.stdout.write(JSON.stringify({ hookSpecificOutput: { hookEventName: 'PermissionRequest', decision } }));تنبيهات: السكربت بيشتغل عند كل طلب إذن لأوامر Bash؛ قلّل الطلبات بإضافة الأوامر الآمنة للمسموح بها (دليل الإعدادات) عشان ما يرنّ تلفونك على npm test. وبديل أبسط من القرار بالتلفون: hook على حدث Notification بمطابق permission_prompt بيتصل بس عشان يقلّك «Claude Code بده إذنك، افتح الطرفية»، والقرار بتاخده إنت بالشاشة. تفاصيل الـ hooks: دليل Hooks.
الأخطاء اللي بتكلّفك فلوس أو ملفات، والحدود بصراحة.
أخطاء بتكلّفك
| الغلط | شو بيصير | الصح |
|---|---|---|
| المفتاح مكتوب بالـ SKILL.md أو بالكود | بيروح مع أول git push. | متغيّر بيئة بس (القسم 1). |
| بتخلّي الرقم حقل حرّ («اتصل على…») | الوكيل ممكن يتصل بأرقام ثانية (وتدفع). | الرقم من OWNER_PHONE بس، مكتوب بالقواعد. |
| بتعتبر الصمت موافقة | حذف أو نشر بدون ما توافق. | «نعم واضحة» بس = موافقة. السكيل مكتوب هيك. |
| max_duration طويل | مكالمة معلّقة 30 دقيقة (الافتراضي) على حسابك. | 3 دقايق لقرار. |
| رقم دولي بدون رصيد مشترى | الطلب بيفشل أو ما بيرنّ. | 5$ رصيد أو شحن تلقائي. |
| hook على كل أمر Bash | تلفونك بيرنّ 20 مرة بالساعة. | اسمح بالأوامر الآمنة بالإعدادات، وخلّي المكالمة للخطير. |
| Claude Code بيحكي تفاصيل حساسة بالمكالمة | كلمات سر بنص مكالمة عند طرف ثالث. | القاعدة بالسكيل: ملخّص + سؤال، بدون مفاتيح أو محتوى ملفات. |
تنبيهات صدق
- ما جرّبت المكالمة على رقمي قبل ما أكتب هالدليل. الـ API والحقول من وثائق Bland يوم 2026-11-06، وطريقة الـ skill والـ hooks من وثائق Claude Code بنفس اليوم. القسم 2 موجود عشان تجرّب قبل ما تعتمد.
- «5 دقايق إعداد» كلام Riley؛ عندي: حساب + رصيد + متغيّرات + ملف = ربع ساعة أول مرة.
- التكلفة: سنتات للمكالمة بخطة Start، بس الدولي بده رصيد مشترى. راقب حسابك أول أسبوع.
- الوكيل بيقرأ جوابك من نص مكالمة؛ «نعم» بوسط جملة طويلة ممكن تتفهم غلط. جاوب بكلمة وحدة واضحة، وخلّي الخطوات الخطيرة فعلاً (حذف نهائي، دفع) بموافقتك بالشات مش بالتلفون.
- Bland منصة أمريكية؛ الأرقام والصوت العربي ممكن تختلف جودتهم بين الدول. ما في عندي رقم ثابت عن الأردن أو السعودية.
- مش من Anthropic: لا Bland ولا السكيل منتج رسمي. Claude Code بيوفّر الـ skills والـ hooks، والربط إلك.