SSD Nodes Learn 8GB RAM — $66/سنة
الأدلة Matt Connorبقلم Matt Connor · آخر تحديث في 2026-08-01

Memmy: ذاكرة محلية مشتركة لوكلاء الذكاء الاصطناعي

ثبّت Memmy من المصدر على Ubuntu، وشغّل خدمة الذاكرة على المنفذ 18960، لتخزين ملاحظات Claude Code وCodex وCursor محليًا في قاعدة SQLite واحدة.

ما هو Memmy وما الذي يخزنه

Memmy هو مركز ذاكرة محلي لوكلاء الذكاء الاصطناعي، ويعمل على VPS الخاص بك (خادم خاص افتراضي). يحتفظ بقاعدة بيانات SQLite واحدة لما تعلمه وكلاؤك، ويقرأ كل وكيل على الخادم مخزن البيانات نفسه ويكتب فيه. المشروع هو memmy-agent من MemTensor، ومرخّص بموجب MIT، وإصداره 1.0.4 في يوليو 2026.

لا يهم على الخادم سوى جزء من مكوناته. يتضمن Memmy خدمة ذاكرة تستمع على http://127.0.0.1:18960، وواجهة سطر أوامر memmy-memory (CLI) تتصل بهذه الخدمة، وبيئة عمل مكتبية. بيئة العمل مُعدّة لنظامي macOS وWindows فقط، لذلك تشغّل على VPS يعمل بنظام Linux الخدمة وواجهة CLI. وهذا يكفي لتوفير ذاكرة مشتركة لكل من Claude Code وCodex وCursor.

يصنّف Memmy ما يخزنه ضمن أربع طبقات. L1 Trace هو التبادل الخام: الطلب والاستجابة واستدعاءات الأدوات. L2 Policy هو إجراء مستخلص من عمليات التتبع التي ثبتت فائدتها. L3 World Model هي معرفة مستقرة حول مشروع أو بيئة. Skill هو إجراء قابل للاستدعاء ومشتق من سياسة. تعيّن الخدمة الطبقة عند استيعاب التبادل، لذلك لا تنشئ هذه الطبقات يدويًا.

ما الذي يتغير عند استخدام مركز ذاكرة مشترك مقارنة بذاكرة مستقلة لكل أداة

تأتي كل أداة وكيل اليوم بذاكرتها الخاصة. يحتفظ Claude Code بملفات التعليمات في المستودع. ويحتفظ Cursor بالقواعد في قاعدة بيانات مساحة العمل. ويحتفظ Codex بسجلات الجلسات ضمن ~/.codex. ينتمي كل مخزن إلى أداة واحدة، لذلك تظل المعلومة التي علّمتها لإحدى الأدوات يوم الاثنين مجهولة لأداة أخرى يوم الثلاثاء. وتدفع ثمن ذلك مرتين: مرة في الرموز المميّزة التي تنفقها لإعادة شرح المشروع نفسه، ومرة في العمل الخاطئ عندما يتصرف الوكيل بناءً على افتراض صححته سابقًا في مكان آخر.

ينقل المركز المخزن خارج الأداة. ويقرأ Memmy المخازن الموجودة أيضًا، لذلك لا تبدأ بقاعدة بيانات فارغة. يعرف الماسح ستة مصادر: Claude Code في ~/.claude/projects/**/*.jsonl، وCodex في ~/.codex/sessions/<YYYY>/<MM>/<DD>/rollout-*.jsonl، وOpenCode في ~/.local/share/opencode/opencode.db، وملفات state.vscdb الخاصة بـ Cursor، وقواعد بيانات SQLite الخاصة بـ OpenClaw ضمن ~/.openclaw، وHermes ضمن ~/.hermes. ويمكنك إضافة مصدر يدويًا باستخدام اسم ومسار محلي.

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

هذا هو الجزء الذي يتكامل مع كيفية إدارة Claude Code للسياق داخل جلسة واحدة. تحدد إدارة السياق ما يمكن أن يتسع له إطار واحد. أما مركز الذاكرة فيحدد ما يبقى بعد إغلاق ذلك الإطار.

ما تحتاج إليه على VPS

  • Node.js بإصدار 22 أو أحدث. تتطلبه وثائق Memmy، بينما يأتي Ubuntu 24.04 مع Node 18.
  • git وسلسلة أدوات البناء، لأن better-sqlite3 وحدة أصلية قد تُجمَّع أثناء التثبيت.
  • ذاكرة RAM بسعة 2 GB تقريبًا. يحمّل التثبيت باستخدام root مساحة عمل كبيرة وسلسلة أدوات بناء للواجهة الأمامية.
  • بضعة GB من المساحة الحرة على القرص من أجل node_modules وقاعدة البيانات.
sudo apt update
sudo apt install -y git build-essential python3 curl ca-certificates sqlite3
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
node --version

يجب أن يطبع node --version القيمة v22 أو قيمة أعلى. تعني v18 هنا أن خطوة NodeSource لم تُنفَّذ بنجاح، وسيفشل التثبيت لاحقًا عند فحص محرك المشروع.

تثبيت Memmy من المصدر على Ubuntu 24.04

git clone https://github.com/MemTensor/memmy-agent.git
cd memmy-agent
cp .env.example .env
npm install
npm run memory:build

يترجم npm run memory:build مساحة عمل @memmy/memory إلى Memory/dist. لا يحتاج أي جزء آخر من شجرة المشروع إلى البناء على خادم بلا واجهة رسومية. تحقق من تحميل الوحدة الأصلية:

node -e "require('better-sqlite3'); console.log('better-sqlite3 loads')"

إذا تسبب هذا السطر في ظهور خطأ بدلاً من الطباعة، فهذا يعني أن الوحدة الأصلية لا تتوافق مع إصدار Node لديك. شغّل npm rebuild better-sqlite3، وهو ما يفعله بالضبط برنامج بدء التشغيل الخاص بالمشروع قبل تشغيل أي شيء.

يوثّق README الأمر bash scripts/dev-start.sh باعتباره أمر بدء التشغيل الواحد. لا تشغّله على VPS بلا واجهة رسومية. فهو يشغّل غلاف سطح مكتب Electron وخادم تطوير Vite على المنفذ 19000 إلى جانب خدمة الذاكرة، ويحتاج Electron إلى شاشة عرض. لذلك يتوقف البرنامج النصي أو ينهي التشغيل على خادم لا توجد فيه جلسة رسومية.

شغّل خدمة الذاكرة وتحقق من استجابتها

npm run memory:serve:dev

هذه هي الطريقة الموثقة لتشغيل خدمة الذاكرة من المصدر. تستمع على 127.0.0.1:18960، وتحتفظ بقاعدة البيانات في ~/.memmy/memory-service/memory.sqlite، وتقرأ الإعدادات من ~/.memmy/config.yaml. يوضح README القيم نفسها صراحةً عند الحاجة إلى تحديدها:

npm run memory:serve:dev -- \
  --host 127.0.0.1 --port 18960 \
  --db ~/.memmy/memory-service/memory.sqlite \
  --config ~/.memmy/config.yaml

من جلسة shell ثانية، اسأل الخدمة عما إذا كانت تعمل:

curl -sS http://127.0.0.1:18960/api/v1/health

نقطة النهاية الوحيدة التي لا تطلب رمزًا هي نقطة فحص الصحة، ولذلك فهي الاختبار المناسب. إذا خرج curl بالرمز 7 وظهرت رسالة Failed to connect to 127.0.0.1 port 18960، فلا توجد خدمة تستمع. اقرأ الطرفية التي تشغّل الخدمة، لأن تعطلها عند بدء التشغيل يظهر فيها، والسبب المعتاد هو تعذر تحميل وحدة SQLite الأصلية. يؤكد ss -lntp | grep 18960 المقبس بعد بدء الخدمة.

توجد بقية HTTP API (واجهة برمجة التطبيقات) ضمن /api/v1.

  • يكتب POST /api/v1/memory/add ذاكرةً، ويستعلم POST /api/v1/memory/search.
  • يقرأ GET /api/v1/memory/:id مدخلةً واحدة، ويحذفها DELETE /api/v1/memory/:id.
  • يحدّد POST /api/v1/sessions/open بداية جلسة وكيل، ويحدّد POST /api/v1/sessions/:sessionId/close نهايتها.
  • يسجّل POST /api/v1/turns/start دورةً واحدة، ويقوم POST /api/v1/turns/:turnId/complete بالمثل.
  • تغذّي GET /api/v1/panel/overview و/api/v1/panel/analysis و/api/v1/panel/items لوحة المعلومات.

تحجز Memmy مجموعة من المنافذ، وفي التشغيل دون واجهة تستخدم المنفذ الأول فقط: 18960 للذاكرة، و18970 لفحص صحة البوابة، و18980 لواجهة الويب وHTTP الإداري، و18990 لواجهة API المتوافقة مع OpenAI التي يبدأها memmy serve، ثم 19000 و19010 لخادم التطوير الخاص بالواجهة الأمامية لسطح المكتب. إذا كان أحد هذه المنافذ مستخدمًا على جهازك، فهذه هي القائمة التي ينبغي أن تبحث فيها.

المصدر الفعلي للأمر memmy-memory

هذا هو الموضع الذي يحدث فيه الخطأ عادةً عند التثبيت الأول، لذلك اقرأه من الحزمة بدلًا من التخمين. لا يرتبط اسم الأمر باسم المستودع. يأتي من الحقل bin لمساحة العمل التي تعرّفه:

node -p "JSON.stringify(require('./Memory/package.json').bin)"

يطبع ذلك {"memmy-memory":"./dist/src/cli/index.js"}. لذلك فإن نقطة الدخول المبنية هي Memory/dist/src/cli/index.js، ولا توجد إلا بعد npm run memory:build، لأن عملية البناء هي التي تنشئ dist وتمنح الملف صلاحية التنفيذ. شغّله مباشرةً:

node Memory/dist/src/cli/index.js health

إذا أردت الاسم المختصر في PATH، فأنشئ رابطًا إلى الملف نفسه:

sudo ln -s "$PWD/Memory/dist/src/cli/index.js" /usr/local/bin/memmy-memory
memmy-memory health

تستخدم واجهة CLI القيمة الافتراضية http://127.0.0.1:18960، وتقبل --url و--token و--config و--source و--user-id. وتتمثل أوامرها الفرعية في init وhealth وsearch وadd وget وdelete، إضافةً إلى استدعاءات الجلسات والأدوار التي تستخدمها الوكلاء بدلًا من الأشخاص. ويُعد memmy-memory search "deploy steps" وmemmy-memory add "staging migrates on deploy" الأمرين اللذين يشغّلهما الوكيل غالبًا.

كيف توصل Claude Code بـ Memmy؟

لا يوفّر Claude Code واجهة لإضافات الذاكرة، لذلك لا يتكامل Memmy معه عبر خطاف. التكامل أبسط من ذلك. يشغّل Claude Code الأمر memmy-memory كأمر shell عادي، ويحدّد له ملف تعليمات متى يشغّله. يكتب مثبّت Memmy الموثّق هذا الملف نيابةً عنك: يضع memmy-memory init --agent ملف تعليمات الذاكرة في دليل القواعد الخاص بالوكيل المستهدف.

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

## Memory

Before starting a task, run `memmy-memory search "<topic>"` and read what comes back.
When a task is done, run `memmy-memory add "<what you learned>"` for anything that will matter next session.

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

لا يحتاج الاتجاه الآخر إلى أي إعداد. يقرأ ماسح Memmy مسبقًا ~/.claude/projects/**/*.jsonl، وهو المكان الذي يكتب فيه Claude Code سجلات جلساته. شغّل Memmy على الخادم نفسه الذي تشغّل عليه Claude Code داخل جلسة tmux، وستتحول أعمال الأمس إلى ذاكرة من دون أي إعداد منك.

هل يعمل Memmy كخادم MCP مع Claude Code؟

لا. ومعرفة ذلك توفر عليك وقتًا طويلًا. يتضمن MCP (بروتوكول سياق النموذج) عملاء وخوادم. Memmy عميل. يتصل بخوادم MCP ويتيح أدواتها لبيئة تشغيل وكيله. ولا ينشر نقطة نهاية MCP يمكن لـ claude mcp add الاتصال بها. جسر MCP الوحيد في المستودع تابع لتكامل Composio داخل واجهة API المحلية لتطبيق سطح المكتب، وتربط واجهة API هذه منفذًا عشوائيًا على 127.0.0.1 خلف ترويسة x-memmy-mcp-token الخاصة بها.

تُضبط جهة العميل في ~/.memmy/config.yaml، وهو الملف الذي يشير إليه MEMMY_CONFIG، ضمن tools.mcpServers:

tools:
  mcpServers:
    example:
      type: stdio
      command: npx
      args:
        - "-y"
        - "your-mcp-server"
      toolTimeout: 30
      enabledTools:
        - "*"

يقبل type القيم stdio وsse وstreamableHttp. يعمل خادم stdio كعملية فرعية لـ Memmy، ولذلك يجب أن يكون الأمر الخاص به موجودًا على الجهاز نفسه وأن يعمل باستخدام المستخدم نفسه. إذا كنت تشغّل خوادم MCP على VPS، فأدرجها هنا.

الحفاظ على خصوصية مخزن الذاكرة

يوجد كل ما يملكه Memmy ضمن ~/.memmy: config.yaml ومساحة العمل وmemory-service/memory.sqlite وملفات وقت التشغيل. تحدث عمليات الفحص والإدخال محليًا، وتُكتب الذكريات في ملف SQLite المحلي، لذلك يكون الإعداد الافتراضي محليًا فعلًا.

يوجد مساران يصلان إلى الشبكة. تكون قيمة MEMMY_CLOUD_SERVICE الافتراضية هي https://memmy-api.memtensor.cn، وتدعم وضع الحساب باستخدام الرموز التجريبية الخاصة به، لذلك لا يستدعي وضع مفتاح API هذا المسار مطلقًا. وبرنامج تحسين الذاكرة مفتاح تبديل منفصل في إعدادات الخصوصية، ويظل متوقفًا حتى تشغّله.

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

أبقِ المنفذ 18960 على عنوان loopback. لا يحتاج إلى قاعدة في جدار الحماية، لأن الخدمة المرتبطة بـ 127.0.0.1 لا يمكن الوصول إليها من خارج الجهاز إطلاقًا. اتصل بها من حاسوبك المحمول عبر SSH بدلًا من ذلك:

ssh -N -L 18960:127.0.0.1:18960 you@your-vps

إذا ربطت الخدمة بعنوان أوسع في أي وقت، فاضبط رمزًا مميزًا أولًا. يؤدي ضبط storage.token في ملف الإعداد، أو متغير البيئة MEMMY_MEMORY_TOKEN أو MEMORY_SERVICE_TOKEN، إلى جعل كل نقطة نهاية، باستثناء health، تتطلب bearer token. تدعم قيم الإعداد مراجع ${ENV_NAME}، لذلك يبقى الرمز المميز ومفاتيح API الخاصة بالنماذج خارج الملف نفسه. وهذا هو الأسلوب نفسه المتبع في إبقاء الأسرار خارج وكلاء الذكاء الاصطناعي في كل موضع آخر، كما أن سياسة ufw الافتراضية لمنع الوصول تشكل إجراءً احتياطيًا إذا غيّر إصدار مستقبلي عنوان الربط الافتراضي.

أنشئ نسخة احتياطية من ~/.memmy قبل الوثوق به

memory.sqlite هو مخزن البيانات بالكامل. تُخزَّن المتجهات في الملف نفسه عبر إضافة sqlite-vec، لذلك يكفي ملف واحد للنسخة الاحتياطية. قد يؤدي نسخه باستخدام cp أثناء كتابة الخدمة إلى إنشاء قاعدة بيانات مبتورة. استخدم أمر النسخ الاحتياطي المدمج في SQLite:

mkdir -p ~/memmy-backup
sqlite3 ~/.memmy/memory-service/memory.sqlite ".backup '$HOME/memmy-backup/memory.sqlite'"

ينشئ ذلك نسخة متسقة مع استمرار تشغيل الخدمة. انقلها إلى خارج الخادم وفق جدول زمني، وهذا ما يوفّره restic للتخزين خارج الخادم. فقدان config.yaml يعني فقدان إعدادات المزوّد التي يمكنك إعادة إدخالها. أما فقدان memory.sqlite فيعني فقدان كل ذاكرة، ولا توجد نسخة ثانية منها في أي مكان آخر على الجهاز.

تشغيل خدمة الذاكرة باستخدام systemd

يموت npm run memory:serve:dev في الصدفة مع انتهاء الصدفة. يحافظ ملف الوحدة على تشغيل الخدمة بعد إعادة التشغيل.

[Unit]
Description=Memmy memory service
After=network-online.target

[Service]
Type=simple
User=memmy
WorkingDirectory=/opt/memmy/memmy-agent
EnvironmentFile=/etc/memmy/memory.env
ExecStart=/usr/bin/npm run memory:serve:dev
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

أبقِ الرمز المميز خارج الوحدة. ضعه في /etc/memmy/memory.env، بحيث يكون مملوكًا للحساب root وبالوضع 600:

MEMMY_CONFIG=/home/memmy/.memmy/config.yaml
MEMMY_MEMORY_TOKEN=replace-this-with-a-long-random-string
sudo systemctl daemon-reload
sudo systemctl enable --now memmy-memory
systemctl status memmy-memory --no-pager
curl -sS http://127.0.0.1:18960/api/v1/health

يعني status=203/EXEC في مخرجات الحالة أن systemd لم يتمكن من تشغيل ExecStart على الإطلاق. لذلك تحقّق من which npm: يكون في /usr/bin/npm عند التثبيت باستخدام NodeSource، ويكون في مسار ضمن الدليل الرئيسي للمستخدم عند استخدام nvm، ولن يعثر عليه systemd. إذا بدأت الوحدة ثم خرجت فورًا، فهذا يعني أن الخطأ حدث داخل npm. يعرض journalctl -u memmy-memory -n 50 السبب. الآلية نفسها كما في أي خدمة systemd أخرى على VPS.

ما لا يفعله Memmy بعد

  • لا توجد نسخة مخصصة لسطح مكتب Linux. تغطي نصوص الحزم نظامي macOS وWindows، لذلك لا تتوفر workbench ومعالج الإعداد الأولي ولوحة معلومات الذاكرة على الخادم نفسه.
  • يشغّل memory:serve:dev نقطة إدخال TypeScript من خلال tsx، وهو مسار مخصص للتطوير. يتضمن المستودع أيضًا memory:serve للمخرجات المترجمة. شغّل npm run بلا وسائط لمعرفة النصوص البرمجية المتوفرة فعليًا في نسختك من المستودع.
  • ينشئ الاسترجاع نافذة البحث من أحدث 2,000 صف متجهي، ثم يطبّق اختيار Top-K داخل هذه النافذة. في مخزن كبير جدًا، قد تكون ذاكرة قديمة خارج هذه النافذة.
  • يحدث التضمين بعد الالتقاط، ويُنقل الفشل إلى قائمة انتظار لإعادة المحاولة بدلًا من إيقاف دور الوكيل. قد لا تكون الذاكرة المضافة قبل لحظات قابلة للعثور عليها عبر البحث المتجهي بعد.
  • يعني وجود ملف SQLite واحد وجود عقدة واحدة. لا توجد عنقدة، لذلك يكون الخادم الثاني ذاكرة ثانية منفصلة.

يصف الإصدار 1.0.4 ونحو 329 نجمة حتى July 2026 مشروعًا حديثًا. تتغير الأعلام والمسارات وأسماء النصوص البرمجية بين الإصدارات. اقرأ الحقل bin ومخرجات npm run في نسختك من المستودع بدلًا من الوثوق بأمر منسوخ من أي مكان، بما في ذلك هذا النص.

FAQ

لماذا يعرض فحص الصحة رسالة رفض الاتصال؟

لا توجد خدمة تستمع على المنفذ 18960. يشير رمز خروج curl 7 مع Failed to connect to 127.0.0.1 port 18960 إلى أن خدمة الذاكرة لا تعمل أو أنها توقفت عند بدء التشغيل. لذلك اقرأ مخرجات الطرفية أو السجل الذي بدأت فيه الخدمة. السببان المعتادان هما وحدة better-sqlite3 أصلية لا تتوافق مع إصدار Node لديك، ويمكن إصلاح ذلك باستخدام npm rebuild better-sqlite3، أو استخدام إصدار Node أقدم من 22. تحقّق من المقبس باستخدام ss -lntp | grep 18960 بعد بدء تشغيل الخدمة.

من أين يأتي الأمر memmy-memory بعد البناء من المصدر؟

يأتي من الحقل bin لحزمة مساحة العمل @memmy/memory، وليس من اسم المستودع. شغّل node -p "JSON.stringify(require('./Memory/package.json').bin)" داخل نسخة المستودع، وسيطبع {"memmy-memory":"./dist/src/cli/index.js"}. لا يوجد هذا الملف إلا بعد npm run memory:build، لأن عملية البناء تنشئ dist وتضع علامة التنفيذ على الملف. شغّله باستخدام node Memory/dist/src/cli/index.js health، أو أنشئ رابطًا رمزيًا له داخل /usr/local/bin لاستخدام الاسم المختصر.

هل يمكنني إضافة Memmy إلى Claude Code باستخدام claude mcp add؟

لا. Memmy عميل MCP وليس خادم MCP. يتصل بالخوادم المدرجة ضمن tools.mcpServers في ~/.memmy/config.yaml، ويتيح أدواتها لبيئة التشغيل الخاصة به. يصل Claude Code إلى Memmy بالطريقة الأخرى، وذلك بتشغيل واجهة سطر الأوامر memmy-memory كأمر shell، بالاستناد إلى ملف تعليمات يكتبه memmy-memory init --agent في دليل قواعد الوكيل.

هل يؤدي تشغيل Memmy إلى إرسال ذاكرتي إلى خدمة سحابية؟

تعمل عمليتا الفحص والاستيعاب محليًا، وتُكتب الذكريات في ~/.memmy/memory-service/memory.sqlite على القرص الخاص بك. يشير MEMMY_CLOUD_SERVICE إلى https://memmy-api.memtensor.cn لوضع الحساب ورموز التجربة، وتظل ميزة تحسين الذاكرة معطلة حتى تمكّنها. المسار الذي يجب مراقبته هو موفّر التضمين: إذ يتلقى نموذج تضمين مستضاف نص كل ذكرى يحوّلها إلى متجه. لذلك استخدم نقطة نهاية تديرها بنفسك إذا كان ذلك مهمًا لك.