انتقل إلى المحتوى الرئيسي

الوحدة 14 — الوضع غير التفاعليّ، وCI مع GitHub Actions، وAgent SDK

تنزع هذه الوحدة لوحة المفاتيح: يعمل Claude Code في cron ليليّ، وفي PR على GitHub Actions، وفي سكربت Python من أربعين سطرًا. ثلاث سطوح، وقاعدة واحدة — الـprompt وقائمة الأدوات هما العقد، وما تبقّى تهيئة.

claude -p: الـCLI في الوضع غير التفاعليّ

claude -p "…" (البديل --print) ينفّذ طلبًا دون جلسة تفاعليّة. يُثبّت headless.md وcli-reference.md الأعلام الدقيقة؛ الاختيار المفيد في CI:

العَلَمالدور
-p، --printيُخرج ويُنهي. غير متوافق مع --bg ومع --cloud "tâche"
--bareيتخطّى hooks وskills والأوامر والسب-agents والـplugins وMCP وذاكرة تلقائيّة وCLAUDE.md — يُبقي Bash وRead وEdit. موصى به في CI
--output-format text|json|stream-jsonنصّ، أو JSON (result وsession_id وبيانات وصفيّة)، أو JSON سطرًا سطرًا
--include-partial-messagesفروق تدفّق streaming؛ يتطلّب --print --output-format stream-json --verbose
--verboseتسجيل دورًا دورًا
--forward-subagent-textيُعيد بثّ نصّ وأفكار السب-agents (v2.1.211+)
--json-schema '{…}'يفرض مخطّط JSON، ويملأ structured_output
--max-turns <N>سقف الأدوار في print، يفشل عند التجاوز
--continue، -c / --resume، -r <id|nom>يستأنف آخر محادثة / جلسة محدَّدة
--no-session-persistenceلا يحفظ الجلسة على القرص (print فقط)
--allowedTools "Bash,Read,Edit" (بديل --allowed-tools)يُوافق تلقائيًّا وفق صياغة قواعد الصلاحيّة
--disallowedTools "…"يسحب أداةً ("Edit") أو يرفض نمطًا (Bash(rm *))
--tools "…"يُضيّق قائمة الأدوات المضمَّنة؛ "" يُعطِّل الكلّ، "default" يُعيد الكلّ
--permission-mode default|acceptEdits|plan|auto|dontAsk|bypassPermissionsالوضع الابتدائيّ. تحت -p، الافتراضيّ Manual على كلّ الخطط
--permission-prompts host|noneمن يجيب عن الطلبات؛ none يرفض بلا مشغِّل (v2.1.259+)
--permission-prompt-tool mcp_xيُفوِّض الطلبات لأداة MCP
--append-system-prompt "…" / --append-system-prompt-fileيُضيف نصًّا إلى prompt النظام الافتراضيّ
--system-prompt "…" / --system-prompt-fileيستبدل prompt النظام كاملًا
--mcp-config <file|json>يُحمِّل خوادم MCP؛ ينتظر اتّصالها حتّى MCP_TIMEOUT (30 ث)
--add-dir <path>يُضيف مجلّدًا لنطاق القراءة/التحرير
--model <alias>sonnet أو opus أو haiku أو fable أو اسم كامل
--effort low|medium|high|xhigh|max|ultracodeمستوى مجهود الجلسة
--agents '{"reviewer":{…}}'يُعرِّف سب-agents ديناميكيًّا بـJSON

حركتان أساسيّتان في CI: تمرير stdin (مسقوف بـ10 MB) وقراءة رمز الخروج (0 نجاح، غير الصفر إخفاق، 143 عند SIGTERM). --bare جوهريّ: بدونه، يُحمِّل -p hooks وMCP وCLAUDE.md من المجلّد الجاري دون نافذة ثقة. يُدرج --output-format json قيمة total_cost_usd وتوزيعًا بحسب النموذج — مفيد لمتابعة الإنفاق دون المرور عبر /usage.

cat build-error.txt | claude --bare -p 'السبب الجذريّ في جملة واحدة' \
--output-format json --max-turns 3 --allowedTools "Read" > diag.json

السكربت triage.sh: فرز issues ليلًا

يستقبل Kiosque عشرات issues سيّئة الوسم أسبوعيًّا. cron في الساعة الثالثة يُفوِّض الفرز إلى Claude، مستعملًا فقط ما هو رسميّ: -p و--bare و--output-format json و--json-schema و--allowedTools و--permission-mode dontAsk و--max-turns.

#!/usr/bin/env bash
# scripts/triage.sh — يُصنّف issues المفتوحة
set -euo pipefail
export ANTHROPIC_API_KEY="${ANTHROPIC_API_KEY:?absent}"

for id in $(gh issue list --state open --json number --jq '.[].number'); do
body=$(gh issue view "$id" --json title,body --template '{{.title}}\n\n{{.body}}')
echo "$body" | claude --bare -p \
"صنّف هذه issue: bug|feature|question|doublon. اقترح من 1 إلى 3 labels وأولويّة p1|p2|p3." \
--output-format json --max-turns 2 \
--permission-mode dontAsk --allowedTools "Read" \
--json-schema '{"type":"object","required":["kind","priority","labels"],
"properties":{"kind":{"enum":["bug","feature","question","doublon"]},
"priority":{"enum":["p1","p2","p3"]},
"labels":{"type":"array","items":{"type":"string"}}}}' \
| jq -r '.structured_output | @json' \
| xargs -I{} gh issue edit "$id" --add-label "$(echo {} | jq -r '.labels|join(",")')" \
--add-label "$(echo {} | jq -r '.kind + \"/\" + .priority')"
done

--permission-mode dontAsk يرفض كلّ ما ليس مأذونًا به، و--max-turns 2 يُقفل كلفة كلّ issue، و--json-schema يضمن كائنًا قابلًا للاستغلال بواسطة gh.

GitHub Actions و@claude

يصف github-actions.md الحركة anthropics/claude-code-action@v1. التثبيت السريع: /install-github-app من Claude Code يُثبِّت تطبيق GitHub، ويُخزِّن سرًّا (ANTHROPIC_API_KEY أو CLAUDE_CODE_OAUTH_TOKEN مستحصَل عبر claude setup-token)، ويفتح PR بالـworkflow. يدويًّا: ثبِّت التطبيق، أضِف السرّ، انسخ examples/claude.yml.

وضعان يُكتشفان تلقائيًّا:

  • تفاعليّ (بلا مُدخَل prompt): يستجيب Claude حين يُذكَر @claude في متن/عنوان issue جديدة، أو في تعليق PR/issue، أو في تعليق مراجعة. يجب أن يكون للكاتب وصول write (إلّا allowed_non_write_users مع github_token داخليّ) وألّا يكون bot (إلّا allowed_bots).
  • أتمتة (مع prompt): يعمل على أيّ حدث، بما فيه schedule. الخرج افتراضيًّا في السجلّ؛ للنشر على PR، يجب أن يطلبه الـprompt وأن تعرف أداةٌ كيفيّة النشر.

لـKiosque، يستجيب .github/workflows/claude.yml للـmentions ويُشغّل المراجعة:

# .github/workflows/claude.yml
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
jobs:
claude:
if: contains(github.event.comment.body, '@claude')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
actions: read
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 1
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
claude_args: >
--max-turns 8 --model claude-sonnet-5
--allowedTools "Bash(make test),Bash(ruff *),Read,Edit"

الأسطر غير الاعتياديّة: id-token: write (مصادقة التطبيق)، وactions: read (نتائج CI)، وحارس if: (لا يُشعل runner من غير سبب). يقبل claude_args أيّ علم من cli-reference.md. لمراجعة تلقائيّة، job ثانٍ يستدعي plugin code-review مع plugin_marketplaces وplugins وprompt: "/code-review:code-review --comment …" — دون --comment، تبقى المكتشفات في السجلّات. مزوّد سحابيّ: ثلاثة مدخلات متبادلة الاستبعاد use_bedrock: "true" وuse_vertex: "true" وuse_foundry: "true"، مع OIDC. تتبع GitLab CI/CD نموذجًا قريبًا (image: node:24-alpine3.21، تثبيت عبر claude.ai/install.sh، ثمّ claude -p "${AI_FLOW_INPUT}" --permission-mode acceptEdits)؛ في مرحلة بيتا، وتُشرِف عليه GitLab.

انتبه لسلاسل CI: إن مرّرت github_token: ${{ secrets.GITHUB_TOKEN }} للـaction، فلن تُشغِّل commits Claude أيّ workflow آخر (حجب افتراضيّ في GitHub). احذف السطر ليدفع Claude بصفة تطبيق Claude Code — عندها ستُطلق commits حدثَي push وpull_request.

الجدولة: /loop و/goal والروتين

يُكرِّر /loop prompt بفاصل داخل الجلسة؛ صيغتان bare token (30m) أو شرطًا (every 2 hours)، ووحدات s وm وh وd. بلا prompt، يُنفِّذ Claude prompt الصيانة المضمَّن (أو .claude/loop.md / ~/.claude/loop.md). المهمّة المتكرّرة تنتهي صلاحيّتها بعد 7 أيّام؛ Esc يقطع تكرارًا. يُفرِّق scheduled-tasks.md بين /loop، والروتين السحابيّ (/schedule، claude.ai/code/routines)، ومهامّ Desktop.

/goal <condition>: بعد كلّ دور، يُقيِّم Haiku افتراضيًّا هل يصمد الشرط. ثلاثة أحكام: Not yet met وMet وImpossible. الشرط الفعّال يُسمّي حالةً قابلة للقياس، ودليلًا، وقيدًا (4000 محرف حدًّا أقصى). في الوضع غير التفاعليّ، claude -p "/goal …" يعمل حتّى الحلّ؛ أضِف --output-format stream-json --verbose، وإلّا لن يظهر شيء قبل النهاية.

Agent SDK: الحلقة نفسها، برنامجًا

يضع agent-sdk__overview.md التكافؤ: يعرض Agent SDK «الأدوات نفسها، والحلقة الوكيلة نفسها، وإدارة السياق نفسها كـClaude Code»، عبر حزمتَين — claude-agent-sdk (Python 3.10+) و@anthropic-ai/claude-agent-sdk (Node 18+)، تتضمّنان الثنائيّ الأصيل. المصادقة بمفتاح API (ANTHROPIC_API_KEY، أو CLAUDE_CODE_USE_BEDROCK=1 أو CLAUDE_CODE_USE_VERTEX=1 أو CLAUDE_CODE_USE_FOUNDRY=1).

نقطة الدخول: query(...)، مُكرِّر لا متزامن يبثّ الرسائل — AssistantMessage، وطلبات الأدوات، وResultMessage. خيارات Python مفيدة (agent-sdk__python.md): allowed_tools وdisallowed_tools وsystem_prompt (سلسلة حرّة، أو {"type": "preset", "preset": "claude_code", "append": "…"} أو {"type": "file", "path": "…"})، وmcp_servers وpermission_mode وmax_turns وmodel وcwd وadd_dirs وenv وhooks. الـAPI نفسها بـcamelCase في جانب TypeScript. خرج مُنظَّم: JSON Schema حجّةً، فيصل الجواب إلى structured_output.

notes-de-version.py: 40 سطرًا من SDK في Python

في Kiosque، عند كلّ tag، توليد الملاحظات من الـcommits. قائمة أدوات مُصغَّرة (Bash، Read)، وpermission_mode: acceptEdits، وmax_turns للإقفال.

# scripts/notes_de_version.py
import asyncio
import json
from claude_agent_sdk import (
query, ClaudeAgentOptions, AssistantMessage, ResultMessage,
)

PROMPT = (
"ولّد ملاحظات الإصدار للـtag الجاري. استخدم `git log`، "
"استخرج الـcommits منذ آخر tag، اجمعها في أقسام "
"'ميزات'، 'إصلاحات'، 'داخليّة'. أجب بالعربيّة، "
"بلا emojis. أعِد Markdown النهائيّ فقط."
)

OPTIONS = ClaudeAgentOptions(
allowed_tools=["Bash", "Read"],
permission_mode="acceptEdits",
max_turns=6,
system_prompt={"type": "preset", "preset": "claude_code",
"append": "يجب أن تسع الملاحظات في صفحة A4 واحدة."},
)

async def main() -> None:
async for msg in query(prompt=PROMPT, options=OPTIONS):
if isinstance(msg, AssistantMessage):
for block in msg.content:
if hasattr(block, "text"):
print(block.text)
elif hasattr(block, "name"):
print(f"[أداة] {block.name}")
elif isinstance(msg, ResultMessage):
print(f"--- انتهى: {msg.subtype}")

if __name__ == "__main__":
asyncio.run(main())

يُشغَّل بـ uv run scripts/notes_de_version.py. في الإنتاج، صفِّ كتل النصّ للنشر التلقائيّ في release GitHub.

SDK أم -p

يفوز -p كلّما وسع الـprompt سطر shell وسع الناتج JSON قابلًا للاستغلال بواسطة jq. يصبح الـSDK ضروريًّا لاعتراض كلّ أداة (callback canUseTool)، أو إدارة عدّة جلسات متزامنة في العمليّة نفسها، أو خلط المنطق الأعماليّ باستدعاء الأدوات، أو تعريض خدمة HTTP تُستأنف بالـID.

سياق معادٍ

دون --bare، يُحمِّل claude -p hooks وخوادم MCP من .mcp.json بلا نافذة ثقة. في cron، وفي Actions، وفي pre-commit: --bare افتراضيًّا، و--allowedTools صريح، و--permission-prompts none.

SIGTERM يُغلق بالرمز 143 دون إنهاء الدور؛ وSIGINT يُنهي الدور ثمّ يخرج؛ وinterrupt() في الـSDK مكافئ برمجيّ. تعمل hooks SessionEnd قبل الإغلاق. bash في الخلفيّة يُنهى بعد خمس ثوانٍ من النتيجة النهائيّة؛ سب-agent في الخلفيّة يُبقي -p منتظرًا، بسقف عشر دقائق (CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS).

الخلاصة

claude -p مع --bare و--output-format json وغالبًا --json-schema هو أساس أيّ أتمتة قابلة للتكرار؛ وأعلام --permission-mode dontAsk و--permission-prompts none و--allowedTools و--max-turns تُقفِل تشغيلًا غير مراقَب. تُتيح GitHub Actions الوضع التفاعليّ (@claude) ووضع الأتمتة (prompt:) عبر anthropics/claude-code-action@v1 — يقبل claude_args أيّ علم CLI. /loop يُكرِّر بفاصل، /goal يستهدف شرطًا يُقيِّمه نموذج سريع، والـroutines تُجدوِل خارج الجلسة. يعرض Agent SDK في Python وTypeScript الحلقة نفسها عبر query(...) مع allowed_tools وpermission_mode وhooks وmcp_servers وsystem_prompt وخرج مُنظَّم بمخطّط JSON.

الوحدة التالية: «إتقان الكلفة والأمان والنشر ضمن فريق».