SSD Nodes Learn 🎉 VPS من $4.99/شهر
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-07

إعداد سطر حالة Claude Code على خادم VPS

اعرض اسم المضيف والمجلد وفرع Git والنموذج أسفل موجّه Claude Code، لتعرف الخادم الصحيح قبل تنفيذ الأوامر وتتجنب العمل على جلسة SSH الخطأ.

ما الذي يعرضه سطر الحالة في Claude Code

سطر الحالة في Claude Code هو سطر يظهر أسفل موجّه الأوامر ويعرض ناتج سكربت تكتبه. أضف كتلة statusLine إلى settings.json، وحدد فيها أمراً. يشغّل Claude Code هذا الأمر، ويرسل إليه حالة الجلسة بتنسيق JSON عبر الإدخال القياسي، ثم يطبع كل ما يكتبه الأمر إلى الإخراج القياسي.

هذا هو العقد الكامل. يقرأ السكربت JSON من الإدخال القياسي، ويطبع نصاً إلى الإخراج القياسي. يعمل السكربت على جهازك، ولا يُرسل أي شيء يطبعه إلى النموذج، لذلك لا يستهلك أي رموز.

على حاسوب محمول يحتوي على مشروع واحد، يكون هذا مجرد تنسيق بصري. أما على ثلاثة خوادم، فهو حاجز أمان. تبدو كل جلسة Claude Code متطابقة في كل طرفية، ولذلك قد تؤدي أربع نوافذ SSH بلا تسميات إلى تنفيذ عملية ترحيل على الخادم الخطأ. ويمنع سطر الحالة الذي يبدأ باسم المضيف هذا النوع من الأخطاء.

موضع إعداد statusLine في settings.json

ضعه في إعدادات المستخدم داخل ~/.claude/settings.json، وينطبق ذلك على كل مشروع على هذا الجهاز. وتعمل إعدادات المشروع داخل المستودع في .claude/settings.json أيضاً، وتكون لها الأولوية في ذلك الدليل.

{
  "statusLine": {
    "type": "command",
    "command": "~/.claude/statusline.sh"
  }
}

تكون type دائماً "command". وتُشغَّل قيمة command عبر shell، لذلك يمكن أن تكون مساراً إلى script أو أمراً عاديّاً. أثبت صحة الربط قبل كتابة أي script:

{
  "statusLine": {
    "type": "command",
    "command": "hostname -s"
  }
}

شغّل Claude Code وأرسل رسالة واحدة. سيعرض الشريط الموجود أسفل موجه الإدخال الآن اسم المضيف المختصر للخادم. إذا ظل فارغاً، فالمشكلة في الإعداد أو في مربع حوار الثقة، وليست في script. اقرأ «لماذا يبقى statusline فارغاً» أدناه.

توجد ثلاثة مفاتيح اختيارية اعتباراً من August 2026. يضيف padding مسافة أفقية بعدد من المحارف، وتكون قيمته الافتراضية 0. يعيد refreshInterval تشغيل الأمر كل N ثوانٍ بالإضافة إلى المشغلات العادية، وبحد أدنى قدره 1. استخدمه فقط عندما يعرض السطر ساعة أو قيمة تتغير أثناء بقاء الجلسة خاملة. يمنع hideVimModeIndicator عرض النص المضمّن -- INSERT -- عندما يعرض script الخاص بك وضع vim بالفعل.

ما البيانات التي يستقبلها script الخاص بـstatusline؟

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

cat > ~/.claude/statusline-capture.sh <<'EOF'
#!/bin/bash
cat > /tmp/statusline-input.json
echo "captured"
EOF
chmod +x ~/.claude/statusline-capture.sh

وجّه statusLine.command إلى ذلك الملف، وابدأ جلسة، وأرسل رسالة واحدة. يقرأ الشريط captured. انظر الآن إلى البيانات التي وصلت:

jq . /tmp/statusline-input.json

لديك البنية الدقيقة لإصدارك، ويمكنك تكرار ذلك كلما غيّر تحديث ما شيئاً.

الأجزاء المستقرة، وفق التوثيق في August 2026، هي كائنات متداخلة وليست مفاتيح مسطحة. يحتوي model على id وdisplay_name. ويحتوي workspace على current_dir وproject_dir: يحدد current_dir الموضع الحالي للجلسة، بينما يحدد project_dir الموضع الذي شُغّلت منه، ويختلفان بعد تغيير دليل العمل أثناء الجلسة. ويحمل cwd في المستوى الأعلى القيمة نفسها التي يحملها workspace.current_dir. ويحتوي context_window على أعداد الرموز المميزة، إضافة إلى used_percentage المحسوبة مسبقاً. ويحتوي cost على total_cost_usd وعدادات المدة. ويبقى session_id ثابتاً طوال مدة الجلسة، ويكون فريداً بين الجلسات، وهذا مهم للتخزين المؤقت لاحقاً.

تحافظ ثلاث قواعد على عمل script عند تغيّر المخطط.

بعض المفاتيح غائبة وليست null. لا تظهر vim وagent وpr وworktree وeffort إلا عند تفعيل الميزة المطابقة. تؤدي قراءة .vim.mode باستخدام jq -r عند إيقاف وضع vim إلى طباعة السلسلة الحرفية null، ويعرض شريطك null للقارئ. أضف // empty إلى كل selector، لكي تطبع المفاتيح الغائبة لا شيئاً على الإطلاق.

تكون بعض القيم null في البداية. تكون context_window.used_percentage وcontext_window.current_usage بقيمة null قبل استلام أول استجابة من API، وتعود current_usage إلى null بعد /compact حتى تعيد المكالمة التالية تعبئتها. لذلك يحتاج عرض نسبة السياق في الشريط إلى // 0، وإلا فإنه يقرأ null خلال الثواني الأولى من كل جلسة. قبل وضع هذا الرقم في شريط، من المفيد معرفة كيفية امتلاء نافذة السياق فعلياً.

لا يوجد فرع git في JSON. لا يبلّغ أي حقل عنه. وأي فرع يظهر في شريطك يأتي من تشغيل script للأمر git نفسه.

نص حالة يتدهور بدلاً من أن يتعطل

هذه هي النسخة الجاهزة للنسخ واللصق. تطبع اسم المضيف، والدليل الحالي، وفرع git، واسم النموذج. لكل حقل قيمة احتياطية، لذلك ينتج حتى كائن JSON فارغ سطراً قابلاً للاستخدام.

#!/bin/bash
# ~/.claude/statusline.sh
input=$(cat)

# Read one field. Prints nothing when the key is missing or null.
field() { printf '%s' "$input" | jq -r "$1 // empty" 2>/dev/null; }

HOST=$(hostname -s 2>/dev/null)
[ -z "$HOST" ] && HOST="host"

DIR=$(field '.workspace.current_dir')
[ -z "$DIR" ] && DIR=$(field '.cwd')
[ -z "$DIR" ] && DIR="$PWD"

MODEL=$(field '.model.display_name')
[ -z "$MODEL" ] && MODEL="claude"

SHORT="$DIR"
if [ -n "$HOME" ]; then
  case "$DIR" in
    "$HOME") SHORT="~" ;;
    "$HOME"/*) SHORT="~/${DIR#"$HOME"/}" ;;
  esac
fi

BRANCH=""
if git -C "$DIR" rev-parse --git-dir >/dev/null 2>&1; then
  BRANCH=$(git -C "$DIR" branch --show-current 2>/dev/null)
  [ -z "$BRANCH" ] && BRANCH="detached"
fi

CYAN=$'\033[36m'
YELLOW=$'\033[33m'
DIM=$'\033[2m'
RESET=$'\033[0m'

LINE="${CYAN}${HOST}${RESET} ${SHORT}"
[ -n "$BRANCH" ] && LINE="${LINE} ${YELLOW}${BRANCH}${RESET}"
LINE="${LINE} ${DIM}${MODEL}${RESET}"

printf '%s\n' "$LINE"

تمر كل قراءة عبر field، الذي يضيف // empty، لذلك ينتج المفتاح الذي أُعيدت تسميته أو حُذف سلسلة فارغة، ويوفّر السطر التالي قيمة افتراضية. ينتقل الدليل احتياطياً من workspace.current_dir إلى cwd ثم إلى $PWD. ويأتي الفرع من git -C "$DIR" بدلاً من استخدام git مجرداً، لذلك يطابق الفرع دائماً الدليل الذي يعرضه الشريط.

احفظ الملف، ثم اجعله قابلاً للتنفيذ:

chmod +x ~/.claude/statusline.sh

إذن التنفيذ ليس اختيارياً. يشغّل Claude Code الأمر عبر shell، لذلك يفشل البرنامج النصي الذي لا يحتوي على +x مع Permission denied، ولا ينتج أي stdout، ويبقى الصف فارغاً من دون ظهور خطأ.

jq يحلل JSON من سطر الأوامر، لكنه غير مثبت على خادم Ubuntu جديد:

sudo apt update && sudo apt install -y jq

ثم وجّه الإعداد إلى البرنامج النصي، باستخدام كتلة settings.json الأولى أعلاه.

اختبر البرنامج النصي قبل أن تثق به

شغّله يدوياً مرتين. أولاً باستخدام كائن جلسة عادي:

echo '{"model":{"display_name":"Opus"},"workspace":{"current_dir":"/srv/api"},"session_id":"t1"}' | ~/.claude/statusline.sh

تحصل على اسم المضيف، ثم /srv/api، ثم Opus. لا يظهر أي فرع، لأن /srv/api على جهازك ليس مستودع git على الأرجح.

ثانياً، اختبر التدهور، وهو الاختبار الذي يتجاهله الناس:

echo '{}' | ~/.claude/statusline.sh

الكائن الفارغ هو أسوأ حالة يمكن أن يسلّمك إياها تغيير في المخطط. يظل السطر يطبع اسم المضيف، والدليل الحالي من $PWD، والكلمة claude في موضع اسم النموذج. لا يحدث أي تعطل، ولا يطبع أي شيء null. ينجو البرنامج النصي الذي يجتاز هذا الاختبار من إعادة تسمية أحد الحقول، لأن الحقل المعاد تسميته والحقل المفقود يمثلان الحدث نفسه بالنسبة إلى البرنامج النصي.

ما ينبغي أن تراه

يُعرَض سطر الحالة في صف مستقل فوق شارات التذييل المضمّنة، ولا يستبدلها. في الإعداد العامل، يتكوّن من صف واحد: اسم المضيف المختصر باللون السماوي، ثم دليل العمل مع اختصار الدليل المنزلي إلى ~، ثم اسم الفرع باللون الأصفر عندما يكون الدليل مستودع git، ثم اسم النموذج بخفوت. يكون قريباً من web-01 ~/api main Opus، مع تلوين هذه الأجزاء الأربعة.

يعيد الصف تشغيل البرنامج النصي عند بدء جلسة، بما في ذلك استئنافها، وعند وصول رسالة مساعد جديدة، وبعد اكتمال /compact، وعند تغيّر وضع الأذونات، وعند تبديل وضع vim، وكذلك عند كل نبضة refreshInterval إذا ضبطت واحدة. تُؤجَّل التحديثات لمدة 300 ms، لذلك يؤدي تتابع التغييرات إلى تشغيل البرنامج النصي مرة واحدة. يختفي الشريط أثناء الإكمال التلقائي، وقائمة المساعدة، ومطالبات الأذونات، ثم يظهر مجدداً.

سبب تقديم اسم المضيف

عندما تُبقي وكلاء يعملون على أكثر من خادم، تكون الطرفية هي الشيء الوحيد الذي يخبرك بمكانك، لكن الطرفيات قد تعرض معلومات مضللة. افتح اتصال ssh ثانياً من داخل جزء tmux، وغالباً ما يحتفظ عنوان النافذة بالاسم القديم، لأن العنوان تضبطه صدفة أوامر لم تتعرف قط إلى انتقالها. اترك Claude Code قيد التشغيل في جلسة tmux منفصلة على VPS، ثم أعد الاتصال بها بعد يوم، ولن تجد على الشاشة ما يميز خادم البناء من خادم الإنتاج.

يختلف سطر الحالة لأنه يُعرض بواسطة Claude Code نفسه لكل جلسة، اعتماداً على البيانات التي تحتفظ بها الجلسة. لا يمكن أن يرثه من الجزء الخطأ، ولا يمكن أن تتركه مطالبة shell قديماً لأنها لم تُحدّث. وما يعرضه هو الخادم الذي يكتب الوكيل ملفاته عليه.

خصص لوناً لكل خادم حتى تتعرف إليه قبل قراءة اسمه. أضف السطرين التاليين فوق تعيين LINE=:

CODE=$(printf '%s' "$HOST" | cksum | cut -d' ' -f1)
HOST_COLOR=$(printf '\033[%dm' "$((31 + CODE % 6))")

استخدم بعد ذلك ${HOST_COLOR} بدلاً من ${CYAN}. يعرض cksum قيمة checksum لاسم المضيف، لذلك يُطابق الاسم نفسه اللون نفسه دائماً ضمن النطاق من 31 إلى 36، أي من الأحمر إلى السماوي. انسخ السكربت نفسه إلى كل خادم، وسيعرض كل خادم تسميته بنفسه.

ويستحق عرض الدليل مكانه للسبب نفسه. يفصل بين /srv/api و/srv/api-staging ضغط مفتاح واحد في أمر ssh، لكن تأثيرهما قد يفصل بين حادثتين كاملتين. النموذج والفرع هما العنصران الآخران اللذان يستحقان المساحة: يوضح النموذج الجلسة التي استأنفتها، ويوضح الفرع ما إذا كان الوكيل على وشك تنفيذ commit إلى main.

تجعل الشاشة الصغيرة كل ذلك أوضح، إذ لا يوجد عنوان نافذة يمكن الاعتماد عليه. إذا كان هذا هو إعدادك، فراجع تشغيل Claude Code من هاتف.

اجعل البرنامج النصي سريعاً

يعمل البرنامج النصي عند كل رسالة من المساعد، ويلغي Claude Code التنفيذ الجاري عند وصول تحديث جديد. لذلك يعرض البرنامج النصي البطيء نصاً قديماً أو لا يعرض أي نص.

تستغرق كل استدعاءات jq بضع ميلي ثوانٍ. أمّا git فهو الجزء الذي يصبح بطيئاً: يستغرق git status في مستودع كبير مع ذاكرة تخزين مؤقت باردة مئات الميلي ثواني. يتجنب البرنامج النصي أعلاه git status عمداً، ويستدعي git branch --show-current الذي يقرأ .git/HEAD ويعيد النتيجة فوراً.

إذا أضفت عملية أثقل، فخزّن نتيجتها في ملف وحدّثها كل بضع ثوانٍ. اجعل مفتاح الملف هو الجلسة:

CACHE="/tmp/statusline-$(field '.session_id')"

استخدم session_id، وليس $$. يمثّل $$ معرّف العملية الخاص بالبرنامج النصي، وهو يختلف في كل استدعاء، لذلك لا تنجح أبداً ذاكرة تخزين مؤقت تعتمد عليه، وتتحمل التكلفة الكاملة في كل مرة. يبقى session_id ثابتاً طوال الجلسة ويختلف بين الجلسات، لذلك لا يمكن لجلسَتَي Claude Code تعملان في مستودعين مختلفين قراءة اسم الفرع المخزّن مؤقتاً الخاص بإحداهما.

هناك حد آخر ينبغي معرفته: لا يعمل tput cols داخل برنامج نصي لسطر الحالة. يلتقط Claude Code الناتج بدلاً من إرفاق البرنامج النصي بالطرفية، لذلك لا توجد قيمة يمكن استخدامها لاكتشاف العرض. يضبط Claude Code متغيرَي البيئة COLUMNS وLINES قبل تشغيل الأمر، بدءاً من الإصدار v2.1.153، لذلك اقرأ $COLUMNS عندما تحتاج إلى تحديد مقدار النص الذي ستطبعه.

لماذا يبقى سطر الحالة فارغاً

لا يظهر أي شيء إطلاقاً. تحقق من بت التنفيذ باستخدام ls -l ~/.claude/statusline.sh، ثم شغّل البرنامج النصي يدوياً باستخدام الإدخال الوهمي أعلاه. إذا طبع سطراً في shell ولم يطبعه في Claude Code، فابدأ باستخدام claude --debug، الذي يسجّل رمز الخروج وstderr لأول تشغيل لسطر الحالة في الجلسة.

يقول سجل التصحيح Status line command skipped: workspace trust not accepted. ينفّذ سطر الحالة أمراً في shell، لذلك يخضع لبوابة الثقة في مساحة العمل نفسها التي تخضع لها hooks. إلى أن توافق على مربع حوار الثقة لهذا الدليل، لن يُشغَّل الأمر. يحدث ذلك كثيراً على VPS، حيث تكون كل عملية clone جديدة في دليل لم يسبق لـClaude Code رؤيته. أعد تشغيل Claude Code في ذلك الدليل ووافق على مربع الحوار.

كل شيء فارغ وdisableAllHooks مضبوط. يعطّل "disableAllHooks": true في settings.json سطر الحالة أيضاً، لأنه بوابة تنفيذ shell نفسها. أزله أو اضبطه على false.

يطبع الصف null. وصل محدِّد jq إلى مفتاح مفقود أو قيمته null، ويطبع jq -r قيمة null في صورة الأحرف الأربعة null. أضف // empty للنص و// 0 للأرقام.

يصبح الصف فارغاً مباشرة بعد تعديل البرنامج النصي. يؤدي أمر ينتهي برمز غير صفري، أو لا يطبع شيئاً، إلى إفراغ الصف. السبب المعتاد هو سطر أخير مثل [ -n "$BRANCH" ] && LINE="..."، الذي ينتهي بالرمز 1 عندما يكون الفرع فارغاً، ويحمل معه رمز خروج البرنامج النصي بأكمله. أبقِ printf في النهاية، أو أضف exit 0.

تظهر رموز الهروب كنص حرفي مثل \e]8;; في الشريط. استخدم printf '%b' بدلاً من echo -e. تحتاج روابط OSC 8 القابلة للنقر أيضاً إلى طرفية تدعمها، وقد يزيل tmux أو SSH هذه المتتاليات، لذلك يكون اللون العادي خياراً أكثر أماناً على خادم بعيد.

يُقتطع الجانب الأيمن من الصف. تشترك إشعارات النظام وعداد الرموز في الوضع المطوّل في الصف نفسه من الجهة اليمنى، وتؤدي الطرفية الضيقة إلى تداخل المحتوى. اجعل المخرجات قصيرة. للحصول على حساب فعلي للاستخدام بدلاً من رقم معروض في شريط، راجع كيفية احتساب Claude Code للرموز المميزة.

FAQ

أين يوجد إعداد سطر الحالة في Claude Code؟

يوجد في settings.json، ضمن كتلة statusLine، مع ضبط type على "command" وضبط command على مسار script أو أمر shell. توجد إعدادات المستخدم في ~/.claude/settings.json، وتنطبق على كل مشروع على ذلك الجهاز. توجد إعدادات المشروع في .claude/settings.json داخل repository، وتكون لها الأولوية في ذلك الدليل. تُعاد قراءة الإعدادات تلقائياً، لكن لا يظهر التغيير إلا عند مشغّل التحديث التالي، مثل رسالتك التالية.

لماذا يظهر سطر حالة Claude Code فارغاً؟

تغطي أربعة أسباب معظم الحالات. قد يفتقر script إلى بت التنفيذ، فيُرجع shell الرمز Permission denied ولا يصل شيء إلى stdout. قد لا تكون قد وافقت على مربع حوار الثقة في مساحة العمل، ويسجّل claude --debug الرمز Status line command skipped: workspace trust not accepted. وقد يكون disableAllHooks هو true، ما يعطّل سطر الحالة ضمن القاعدة نفسها. أو قد ينتهي script برمز غير صفري، فيصبح الصف فارغاً. اختبره يدوياً أولاً: يجب أن يطبع echo '{}' | ~/.claude/statusline.sh شيئاً.

هل يتضمن JSON الخاص بسطر الحالة فرع git؟

لا. يتضمن JSON حالة الجلسة، مثل النموذج، وأدلة مساحة العمل، وأرقام نافذة السياق، والتكلفة. لا يحتوي على أي معلومات عن git. يظهر الفرع في الشريط نتيجة استدعاء script الخاص بك للأمر git branch --show-current. مرّر الدليل من JSON باستخدام git -C "$DIR"، حتى يطابق الفرع دائماً الدليل الذي يعرضه الشريط.

هل يستهلك سطر الحالة tokens أو يبطئ الجلسة؟

لا يستهلك أي tokens، لأن script يعمل محلياً ولا يُرسل ناتجه إلى النموذج. تقع مسؤولية السرعة عليك. يُشغَّل الأمر مع كل رسالة من assistant بعد تأخير debounce مدته 300 ms، ويلغي Claude Code عملية التشغيل الجارية عند وصول تحديث جديد، لذلك يعرض script الذي يستغرق ثانية كاملة نصاً قديماً. تجنّب git status في repositories الكبيرة، وخزّن مؤقتاً كل ما يستغرق وقتاً طويلاً في ملف يعتمد مفتاحه على session_id.

كيف أعرض سطر حالة مختلفاً على كل خادم؟

احتفظ بـscript واحد ودعه يقرأ الجهاز. يطبع script أعلاه $HOSTNAME مع استخدام hostname -s كقيمة احتياطية، لذلك يضع الملف نفسه المنسوخ إلى كل جهاز اسم كل جهاز بصورة صحيحة، كما تمنح حيلة تلوين checksum كل hostname لوناً خاصاً به. إذا احتاج أحد الخوادم إلى تخطيط مختلف، فضع كتلة statusLine في إعدادات المشروع الخاصة بـrepository الذي تعمل فيه على ذلك الجهاز، لأن إعدادات المشروع تتغلب على إعدادات المستخدم في ذلك الدليل.