Memmy؛ حافظه مشترک عاملهای AI روی VPS
Memmy یک مخزن حافظه محلی مشترک برای عاملهای AI است. آن را از کد منبع روی Ubuntu بسازید، سرویس را روی پورت 18960 اجرا کنید و یادداشتها را محلی نگه دارید.
Memmy چیست و چه چیزی ذخیره میکند
Memmy یک مرکز حافظه محلی برای عاملهای هوش مصنوعی است که روی VPS (سرور خصوصی مجازی) خودتان اجرا میشود. این ابزار یک پایگاه داده SQLite از آموختههای عاملها نگه میدارد و هر عامل روی همان سرور از همان مخزن داده میخواند و در آن مینویسد. این پروژه memmy-agent از MemTensor است، با مجوز MIT منتشر شده و در ژوئیه 2026 در نسخه 1.0.4 قرار دارد.
فقط بخشی از قابلیتهای آن در یک سرور اهمیت دارد. Memmy یک سرویس حافظه ارائه میکند که روی http://127.0.0.1:18960 به درخواستها گوش میدهد، یک memmy-memory رابط خط فرمان (CLI) دارد که با آن سرویس ارتباط برقرار میکند، و یک محیط کاری دسکتاپ ارائه میدهد. محیط کاری فقط برای macOS و Windows بستهبندی شده است؛ بنابراین در یک VPS لینوکس، سرویس و CLI را اجرا میکنید. این برای فراهمکردن حافظه مشترک میان Claude Code، Codex و Cursor کافی است.
Memmy دادههای ذخیرهشده را در چهار لایه دستهبندی میکند. L1 Trace همان نوبت خام است: درخواست، پاسخ و فراخوانیهای ابزار. L2 Policy روشی است که از traceهایی استخراج شده که مفیدبودن آنها ثابت شده است. L3 World Model دانش پایدار درباره یک پروژه یا محیط است. Skill روشی قابل فراخوانی است که از یک policy شکل گرفته است. سرویس هنگام دریافت یک نوبت، لایه آن را تعیین میکند؛ بنابراین لازم نیست لایهها را دستی ایجاد کنید.
هاب حافظه مشترک در مقایسه با حافظه جداگانه هر ابزار چه تغییری ایجاد میکند
امروزه هر agent حافظه مخصوص خود را دارد. Claude Code فایلهای دستورالعمل را در repository نگه میدارد. Cursor قوانین را در پایگاهداده workspace خود نگه میدارد. Codex گزارشهای session را در ~/.codex نگه میدارد. هر مخزن فقط به یک ابزار تعلق دارد؛ بنابراین واقعیتی که روز دوشنبه در یک ابزار آموزش دادهاید، روز سهشنبه در ابزار دیگر ناشناخته است. این وضعیت دو هزینه دارد: یکبار بهدلیل tokenهایی که برای توضیح دوباره همان پروژه مصرف میشوند، و بار دیگر بهدلیل کار نادرستی که agent بر اساس فرضی انجام میدهد که قبلاً در جای دیگری اصلاح کردهاید.
هاب، مخزن را از ابزار جدا میکند. Memmy همچنین مخزنهای موجود را میخواند؛ بنابراین کار را از یک پایگاهداده خالی شروع نمیکنید. scanner آن شش منبع را میشناسد: 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. میتوانید با وارد کردن یک نام و یک مسیر محلی، منبعی را بهصورت دستی اضافه کنید.
شمارندههای import با یکدیگر یکسان نخواهند بود و این وضعیت طبیعی است. scanner پیامها را بر اساس منبع و conversation گروهبندی میکند، سپس برای هر turn کامل، یک حافظه L1 مینویسد. یک turn زمانی کامل محسوب میشود که محتوای غیرخالی کاربر را داشته باشد و با یک پیام غیرخالی assistant پایان یابد؛ بنابراین یک session قطعشده هیچ دادهای اضافه نمیکند. پیامها با استفاده از checkpointهای conversation و شناسههای پایدار turn حذف موارد تکراری میشوند. تعداد موارد اسکنشده، تعداد پیامهای importشده و تعداد حافظههای جدید در یک اجرای یکسان با هم تفاوت دارند.
این بخش با نحوه مدیریت context توسط Claude Code در یک session مرتبط است. مدیریت context تعیین میکند چه چیزی در یک پنجره واحد جا میگیرد. هاب حافظه تعیین میکند پس از بستهشدن آن پنجره چه چیزی باقی میماند.
موارد موردنیاز در VPS
- Node.js نسخه 22 یا جدیدتر. مستندات Memmy به آن نیاز دارند و Ubuntu 24.04، Node 18 را ارائه میکند.
gitو زنجیره ابزار ساخت، زیراbetter-sqlite3یک ماژول native است که ممکن است هنگام نصب کامپایل شود.- حدود 2 GB حافظه RAM. نصب root یک workspace بزرگ و زنجیره ساخت frontend را دریافت میکند.
- چند 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 --versionnode --version باید v22 یا بالاتر را نمایش دهد. نمایش v18 در اینجا یعنی مرحله NodeSource اعمال نشده است و نصب در بررسی engine پروژه شکست خواهد خورد.
نصب 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:buildnpm run memory:build، workspace مربوط به @memmy/memory را در Memory/dist کامپایل میکند. برای یک سرور headless، نیازی نیست بخش دیگری از درخت پروژه build شود. بررسی کنید که native module بارگذاری شده است:
node -e "require('better-sqlite3'); console.log('better-sqlite3 loads')"اگر این خط بهجای چاپ خروجی، خطا ایجاد کرد، native module با نسخه Node شما سازگار نیست. دستور npm rebuild better-sqlite3 را اجرا کنید؛ این دقیقاً همان کاری است که اسکریپت start خود پروژه، پیش از راهاندازی هر چیزی انجام میدهد.
README، bash scripts/dev-start.sh را بهعنوان راهاندازی با یک command مستند کرده است. آن را روی یک VPS headless اجرا نکنید. این دستور، پوسته دسکتاپ Electron و یک Vite dev server را روی port 19000 در کنار memory service راهاندازی میکند. Electron به display نیاز دارد؛ بنابراین در سروری که session گرافیکی ندارد، اسکریپت متوقف میشود یا خارج میشود.
سرویس memory را راهاندازی کنید و پاسخگویی آن را بررسی کنید
npm run memory:serve:devاین روش مستند برای اجرای سرویس memory از کد منبع است. سرویس به 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/healthendpoint مربوط به سلامت تنها endpoint است که هرگز token درخواست نمیکند؛ به همین دلیل برای probe مناسب است. اگر curl با code 7 و پیام Failed to connect to 127.0.0.1 port 18960 خارج شود، هیچ پردازشی در حال listening نیست. terminal در حال اجرای سرویس را بررسی کنید، زیرا crash هنگام startup در همانجا نمایش داده میشود و علت معمول، بارگذاری نشدن native SQLite module است. ss -lntp | grep 18960 پس از بالا آمدن سرویس، socket را تأیید میکند.
باقی HTTP API (رابط برنامهنویسی کاربردی) در زیر /api/v1 قرار دارد.
POST /api/v1/memory/addیک memory مینویسد وPOST /api/v1/memory/searchپرسوجوها را اجرا میکند.GET /api/v1/memory/:idوDELETE /api/v1/memory/:idیک entry را میخوانند و حذف میکنند.POST /api/v1/sessions/openوPOST /api/v1/sessions/:sessionId/closeیک agent session را مشخص میکنند.POST /api/v1/turns/startوPOST /api/v1/turns/:turnId/completeیک turn را ثبت میکنند.GET /api/v1/panel/overview،/api/v1/panel/analysisو/api/v1/panel/itemsدادهها را به dashboard ارسال میکنند.
Memmy یک بازه از portها را رزرو میکند و در حالت headless فقط از اولین port استفاده میشود: 18960 برای memory، 18970 برای سلامت gateway، 18980 برای web UI و admin HTTP، 18990 برای API سازگار با OpenAI که memmy serve راهاندازی میکند، و سپس 19000 و 19010 برای dev server مربوط به frontend دسکتاپ. اگر پردازشی روی سیستم شما از قبل یکی از این portها را در اختیار دارد، باید محل بررسی را در همین فهرست پیدا کنید.
فرمان memmy-memory در واقع از کجا میآید
این همان بخشی است که معمولاً نخستین نصب در آن دچار مشکل میشود؛ بنابراین بهجای حدسزدن، آن را از خود بسته بخوانید. نام فرمان هیچ ارتباطی با نام مخزن ندارد. این نام از فیلد bin در workspaceای میآید که آن را تعریف میکند:
node -p "JSON.stringify(require('./Memory/package.json').bin)"این دستور {"memmy-memory":"./dist/src/cli/index.js"} را چاپ میکند. بنابراین entry point ساختهشده Memory/dist/src/cli/index.js است و فقط پس از npm run memory:build وجود دارد، زیرا فرایند build است که dist را ایجاد و فایل را executable میکند. آن را مستقیماً اجرا کنید:
node Memory/dist/src/cli/index.js healthاگر میخواهید نام کوتاه در PATH شما قرار بگیرد، به همان فایل link ایجاد کنید:
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 هستند؛ همچنین فراخوانیهای session و turn را دارد که agentها، نه کاربران، از آنها استفاده میکنند. memmy-memory search "deploy steps" و memmy-memory add "staging migrates on deploy" دو موردی هستند که یک agent بیشتر از همه اجرا میکند.
چگونه Claude Code را به Memmy متصل میکنید؟
Claude Code رابطی برای افزونههای حافظه ندارد؛ بنابراین Memmy به آن متصل نمیشود. این یکپارچهسازی از این هم سادهتر است. Claude Code، memmy-memory را بهعنوان یک فرمان عادی پوسته اجرا میکند و یک فایل دستورالعمل زمان اجرای آن را مشخص میکند. نصبکننده مستند 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 (model context protocol) دارای client و server است. Memmy یک client است. این برنامه به MCP serverها متصل میشود و ابزارهای آنها را در اختیار runtime عامل خودش قرار میدهد. Memmy یک MCP endpoint منتشر نمیکند که claude mcp add بتواند به آن متصل شود. تنها پل MCP موجود در repository، به یکپارچهسازی Composio درون desktop local API تعلق دارد و آن API یک پورت تصادفی را روی 127.0.0.1، پشت سروردادهٔ x-memmy-mcp-token، bind میکند.
سمت client در ~/.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 را میپذیرد. یک server از نوع stdio بهعنوان فرزند Memmy اجرا میشود. بنابراین command آن باید روی همان سیستم وجود داشته باشد و با همان user اجرا شود. اگر از قبل MCP serverها را روی یک VPS اجرا میکنید، باید همان serverها را در اینجا فهرست کنید.
خصوصی نگهداشتن مخزن حافظه
تمام دادههای تحت مالکیت Memmy در مسیر ~/.memmy قرار دارند: config.yaml، فضای کاری، memory-service/memory.sqlite و فایلهای زمان اجرا. اسکن و دریافت داده بهصورت محلی انجام میشود و حافظهها در همان فایل محلی SQLite نوشته میشوند؛ بنابراین وضعیت پیشفرض واقعاً محلی است.
دو مسیر به شبکه دسترسی دارند. MEMMY_CLOUD_SERVICE بهطور پیشفرض روی https://memmy-api.memtensor.cn تنظیم میشود و حالت حساب را با توکنهای آزمایشی آن فعال میکند؛ بنابراین حالت کلید API هرگز آن را فراخوانی نمیکند. برنامه بهبود حافظه یک گزینه جداگانه در تنظیمات حریم خصوصی است و تا زمانی که آن را فعال نکنید، خاموش میماند.
مسیر سومی نیز وجود دارد که بهراحتی نادیده گرفته میشود. اگر یک ارائهدهنده embedding میزبانیشده را پیکربندی کنید، متن هر حافظه برای تبدیل شدن به بردار به آن ارائهدهنده ارسال میشود. ذخیرهسازی محلی در این مورد کمکی نمیکند. تنها راه بستن این مسیر، میزبانی endpoint مربوط به embedding روی سرور خودتان است.
پورت 18960 را روی نشانی loopback نگه دارید. برای آن به قانون firewall نیاز ندارید، زیرا سرویسی که به 127.0.0.1 متصل باشد، از خارج از همان سیستم قابل دسترسی نیست. بهجای آن، از طریق SSH و از لپتاپ خود به آن دسترسی پیدا کنید:
ssh -N -L 18960:127.0.0.1:18960 you@your-vpsاگر زمانی آن را روی نشانی گستردهتری bind کردید، ابتدا یک token تنظیم کنید. تنظیم storage.token در فایل پیکربندی، یا تنظیم متغیر محیطی MEMMY_MEMORY_TOKEN یا MEMORY_SERVICE_TOKEN، باعث میشود هر endpoint بهجز health به bearer token نیاز داشته باشد. مقادیر پیکربندی از ارجاعهای ${ENV_NAME} پشتیبانی میکنند؛ بنابراین token و کلیدهای API مدل شما در خود فایل ذخیره نمیشوند. این همان رویهای است که در بخشهای دیگر برای دور نگهداشتن اسرار از عاملهای هوش مصنوعی استفاده میکنید، و سیاست پیشفرض deny در ufw در صورتی که نسخهای در آینده نشانی bind پیشفرض را تغییر دهد، لایه پشتیبان شما خواهد بود.
پیش از اعتماد به memory.sqlite از memory.sqlite پشتیبان بگیرید
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 فقط باعث از دست رفتن تنظیمات provider میشود که میتوانید دوباره وارد کنید. از دست دادن memory.sqlite به معنای از دست دادن تمام حافظههاست و هیچ بخش دیگری از این ماشین نسخه دومی از آنها ندارد.
اجرای سرویس حافظه تحت systemd
npm run memory:serve:dev در یک shell با پایان shell متوقف میشود. یک فایل واحد، سرویس را پس از راهاندازی مجدد نیز فعال نگه میدارد.
[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-stringsudo 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 را بررسی کنید: در نصب NodeSource مقدار آن /usr/bin/npm است و در nvm به مسیری زیر home کاربر اشاره میکند؛ systemd این مسیر را پیدا نمیکند. اگر واحد بلافاصله شروع و متوقف شود، خطا داخل npm رخ داده است و journalctl -u memmy-memory -n 50 دلیل آن را نمایش میدهد. سازوکار آن مانند هر سرویس systemd دیگری روی یک VPS است.
کارهایی که Memmy هنوز انجام نمیدهد
- نسخه دسکتاپ Linux وجود ندارد. اسکریپتهای بستهبندی macOS و Windows را پوشش میدهند؛ بنابراین workbench، جادوگر onboarding و داشبورد memory روی خود server در دسترس نیستند.
memory:serve:devنقطه ورود TypeScript را از طریقtsxاجرا میکند که یک مسیر توسعه است. مخزن همچنینmemory:serveرا برای خروجی کامپایلشده ارائه میدهد.npm runرا بدون آرگومان اجرا کنید تا ببینید checkout شما واقعاً چه scriptهایی دارد.- فرایند retrieval پنجره جستوجوی خود را از جدیدترین 2,000 ردیف vector میسازد و سپس انتخاب Top-K را در همان پنجره انجام میدهد. در یک store بسیار بزرگ، یک memory قدیمی ممکن است خارج از این پنجره قرار بگیرد.
- embedding پس از capture انجام میشود و خطا بهجای متوقفکردن نوبت agent، وارد صف retry میشود. ممکن است memory که همین لحظه اضافه شده است، هنوز با vector search قابل یافتن نباشد.
- یک فایل SQLite فقط به معنی یک node است. clustering وجود ندارد؛ بنابراین server دوم، memory جداگانه و مستقلی دارد.
نسخه 1.0.4 و حدود 329 ستاره تا July 2026 نشان میدهند که این پروژه هنوز جوان است. flagها، pathها و نام scriptها بین releaseها تغییر میکنند. فیلد bin و خروجی npm run را در checkout خودتان بخوانید و به commandی که از هر منبعی، ازجمله اینجا، کپی شده است اعتماد نکنید.
FAQ
چرا بررسی سلامت، خطای عدم پذیرش اتصال برمیگرداند؟
هیچ فرایندی روی درگاه 18960 در حال گوشدادن نیست. کد خروجی 7 از curl همراه با Failed to connect to 127.0.0.1 port 18960 یعنی سرویس حافظه در حال اجرا نیست یا هنگام راهاندازی متوقف شده است؛ بنابراین ترمینال یا journal مربوط به زمان راهاندازی آن را بررسی کنید. دو علت معمول عبارتاند از یک ماژول بومی better-sqlite3 که با نسخه Node شما سازگار نیست و با npm rebuild better-sqlite3 برطرف میشود، و استفاده از نسخهای پایینتر از Node 22. پس از فعالشدن سرویس، سوکت را با ss -lntp | grep 18960 تأیید کنید.
فرمان memmy-memory پس از ساخت از کد منبع از کجا میآید؟
این فرمان از فیلد bin در بسته workspace با نام @memmy/memory میآید، نه از نام مخزن. فرمان node -p "JSON.stringify(require('./Memory/package.json').bin)" را درون checkout اجرا کنید؛ این فرمان {"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 mcp add به Claude Code اضافه کنم؟
خیر. Memmy یک کلاینت MCP است، نه یک سرور MCP. این برنامه به سرورهای فهرستشده در بخش tools.mcpServers از ~/.memmy/config.yaml متصل میشود و ابزارهای آنها را در اختیار محیط اجرای خودش قرار میدهد. Claude Code از مسیر دیگر به Memmy دسترسی پیدا میکند: با اجرای CLI مربوط به memmy-memory بهعنوان یک فرمان shell؛ این فرایند با فایل دستورالعملی هدایت میشود که memmy-memory init --agent آن را در پوشه قوانین agent مینویسد.
آیا اجرای Memmy خاطرات من را به یک سرویس ابری ارسال میکند؟
اسکن و ورود دادهها بهصورت محلی انجام میشود و خاطرات در ~/.memmy/memory-service/memory.sqlite روی دیسک خودتان نوشته میشوند. MEMMY_CLOUD_SERVICE برای حالت حساب و توکنهای آزمایشی به https://memmy-api.memtensor.cn اشاره میکند و برنامه بهبود حافظه تا زمانی که آن را فعال نکنید، غیرفعال میماند. بخشی که باید زیر نظر بگیرید، ارائهدهنده embedding است: یک مدل embedding میزبانیشده، متن هر خاطرهای را که به بردار تبدیل میکند دریافت میکند؛ بنابراین اگر این موضوع برایتان مهم است، از endpointی استفاده کنید که خودتان اجرا میکنید.