روی این سرور فرمان codex --version نسخه‌ی 0.158.0 را می‌گوید، ولی codex app-server daemon version برای همان لحظه appServerVersion: 0.160.0 را چاپ می‌کند. این دو نسخه از دو مسیر جدا می‌آیند و هیچ‌کدام اشتباه نیستند. در این پست نشان می‌دهیم این اختلاف از کجا می‌آید، با فرمان --from-cli چطور بسته‌ی دیمون روی نسخه‌ی خط فرمان قفل می‌شود، و چرا راه برگشتی که خود مستندات نام می‌برند روی نسخه‌های 0.158.0 و 0.160.0 کار نمی‌کند. همه‌ی عددها لحظه‌ی خواندن: ۵ اکتبر ۲۰۲۶.

دو نسخه از دو مسیر جدا

کدکس روی این ماشین با npm نصب شده است، یعنی فرمان codex در مسیر ابزارهای Node می‌زیند. آن سو، یک دیمون مدیریت‌شده هم وجود دارد که مستقل از فرمان خط فرمان، یک app-server دائمی را نگه می‌دارد و همان چیزی است که کلاینت‌های راه دور به آن وصل می‌شوند. هر کدام نسخه‌ی خودش را دارند:

$ codex --version
codex-cli 0.158.0

# چهار عدد، و فقط یکی از آن‌ها نسخه‌ی فرمان خط فرمان است
$ codex app-server daemon version
{"status":"running","backend":"pid",
 "managedCodexPath":".../packages/app-server-daemon/current/bin/codex",
 "managedCodexVersion":"0.160.0",
 "socketPath":".../app-server-control.sock",
 "cliVersion":"0.158.0","appServerVersion":"0.160.0"}

خروجی بالا یک قرارداد صریح دارد: هر فرمان موفق دقیقا یک شیء JSON در خروجی استاندارد می‌نویسد و گزارش‌های چرخه‌ی کار، backend حل‌شده، مسیر سوکت، نسخه‌ی محلی CLI و نسخه‌ی در حال اجرای app-server را برمی‌گردانند. یعنی دو نسخه‌ی متفاوت در یک خط JSON پاسخ درست و سالم است، نه نشانه‌ی خرابی نصب.

تفاوت این دو مسیر را خود مستند دیمون در نسخه‌ی 0.160.0 توضیح می‌دهد: فرمان‌های چرخه‌ی کار از بسته‌ی انتخاب‌شده‌ی دیمون استفاده می‌کنند، صرف‌نظر از نسخه‌ی CLI فراخواننده، و بسته‌ی موجود را به‌طور ضمنی جایگزین نمی‌کنند. بسته‌ی دیمون هم یک پوشه‌ی کامل با فایل bin/codex، دایرکتوری منابع و codex-package.json است، نه یک باینری لخت.

مسیرنسخهچه چیزی را اجرا می‌کند
فرمان codex0.158.0نشست شما در ترمینال
بسته‌ی current دیمون0.160.0سرور دائمی app-server
مخزن npm0.160.0آخرین نسخه‌ی منتشرشده

جدول بالا سه عدد مستقل است که در همین اجرا خوانده شدند. نسخه‌ی npm از صفحه‌ی بسته در npm و دو عدد دیگر از خروجی خود فرمان آمده‌اند. یک پیام بازبینی‌ناپذیر هم اینجا لازم است: نسخه‌ی 0.158.0 خود یادداشت انتشار 0.158.0 در گیت‌هاب را دارد که در ۲۸ سپتامبر ۲۰۲۶ منتشر شد و در بخش قابلیت‌های تازه، امنیت وب‌سوکت و codex mcp add --oauth-client-secret را فهرست می‌کند.

قفل کردن بسته‌ی دیمون روی نسخه‌ی خط فرمان

مستند دیمون می‌گوید فرمان‌های چرخه‌ی کار بسته‌ی موجود را تعویض نمی‌کنند، و برای همین یک مسیر مستقل وجود دارد: update --from-cli بسته‌ی فراخوان را در پوشه‌ی دیمون کپی می‌کند و آن را pin می‌کند. روی این ماشین همان کار را کردیم و نسخه‌ی در حال اجرای سرور از 0.160.0 به 0.158.0 پایین آمد.

$ codex app-server daemon update --from-cli -y
Replace installed daemon version 0.160.0 with CLI version 0.158.0 from
/root/.hermes/tools/node-26.7.0-linux-x64/lib/node_modules/@openai/codex/.../x86_64-unknown-linux-musl.
The daemon package will be installed in /root/.codex/packages/app-server-daemon.
The selected package will be pinned. Run `codex app-server daemon update`
to return to production updates.
The running daemon will restart; active or queued work may be interrupted.
{"status":"updated","installedVersion":"0.158.0","runningVersion":"0.158.0",
 "message":"The CLI package is selected and pinned. ..."}

# حالا سرور روی همان نسخه‌ی خط فرمان اجرا می‌شود
$ codex app-server daemon version
{"status":"running","managedCodexVersion":"0.158.0",
 "cliVersion":"0.158.0","appServerVersion":"0.158.0"}

آنچه این فرمان روی دیسک انجام داد سه چیز بود. یک کپی کامل ۴۲۴ مگابایتی از بسته‌ی npm ساخت، پیوند current را به آن چرخاند، و نام بسته را از 0.158.0-x86_64-unknown-linux-musl به یک نام با پیشوند local- و یک هش ۶۴ رقمی تبدیل کرد. نام هش‌دار همان نشانه‌ی pin است.

$ du -sh /root/.codex/packages/app-server-daemon/releases/*
424M   .../releases/0.158.0-x86_64-unknown-linux-musl
427M   .../releases/0.160.0-x86_64-unknown-linux-musl
424M   .../releases/local-cf6e8f16dfc4e6b11eeecca046f6ab335d452b2023229013aa9b71b4be3cf26e-x86_64-unknown-linux-musl

$ ls -l /root/.codex/packages/app-server-daemon/current
... current -> .../releases/local-cf6e8f16dfc4e6b11eeecca046f6ab335d452b2023229013aa9b71b4be3cf26e-x86_64-unknown-linux-musl

# فایل انتخاب کانال که پیش از pin وجود داشت و بعد از آن حذف شد
$ ls -l /root/.codex/packages/app-server-daemon/auto-update-version
ls: cannot access '.../auto-update-version': No such file or directory

حذف فایل انتخاب کانال بی‌اهمیت نیست. مستند می‌گوید زمان‌بند به‌روزرسانی فقط وقتی حلقه‌ی جدا را بالا می‌آورد که خودکار بودن روشن باشد، نصب‌کننده کانال پایدار latest را انتخاب کرده باشد، و بسته‌ی مدیریت‌شده فرمان به‌روزرسانی را پشتیبانی کند. وقتی این رکورد پاک شد، دیمون دیگر شرط کانال را نداشت. ما این را با شمارش فرایندها سنجیدیم: پیش از pin یک فرایند app-server daemon pid-update-loop در حال اجرا بود و پس از pin هیچ فرایندی با آن نام باقی نماند.

راه برگشتی که مستند می‌نامد و کار نمی‌کند

پیام خود فرمان راه برگشت را نام می‌برد: برای بازگشت به به‌روزرسانی تولیدی، codex app-server daemon update را اجرا کنید. مستند هم دقیقا همین را می‌گوید و اضافه می‌کند که این فرمان بسته‌های pin‌شده یا محلی را به واجد شرایط تولید برمی‌گرداند. روی هر دو نسخه‌ای که در این آزمایش اجرا شدند، این دستور پذیرفته نشد:

$ codex app-server daemon update -y
error: the following required arguments were not provided:
  --from-cli

Usage: codex app-server daemon update --from-cli --yes

یعنی تنها فرم پذیرفته‌شده، همان فرمی است که pin می‌کند. تلاش دوم را با همان باینری نسخه‌ی 0.160.0 که هنوز روی دیسک بود تکرار کردیم و نتیجه یکی بود. برای همین برگشتن به تولید را دستی انجام دادیم: پیوند current را به بسته‌ی 0.160.0 برگرداندیم، دیمون را ری‌استارت کردیم و کپی محلی را حذف کردیم.

$ ln -sfn /root/.codex/packages/app-server-daemon/releases/0.160.0-x86_64-unknown-linux-musl \
         /root/.codex/packages/app-server-daemon/current
$ codex app-server daemon restart
{"status":"restarted","pid":1223726,"managedCodexVersion":"0.160.0",
 "cliVersion":"0.158.0","appServerVersion":"0.160.0"}

$ rm -rf /root/.codex/packages/app-server-daemon/releases/local-*
$ codex app-server daemon version
{"status":"running","managedCodexVersion":"0.160.0",
 "cliVersion":"0.158.0","appServerVersion":"0.160.0"}

برگشت دستی هم یک پیامد داشت که فقط با شمارش فرایندها معلوم شد. با بازگرداندن پیوند، رکورد کانال هم باید دستی نوشته می‌شد. تا وقتی آن فایل نبود، حلقه‌ی خودکار به‌روزرسانی بالا نیامد. با نوشتن نسخه‌ی کانال و یک ری‌استارت دیگر، فرایند به‌روزرسانی برگشت:

$ printf '%s' '0.160.0-x86_64-unknown-linux-musl' > \
    /root/.codex/packages/app-server-daemon/auto-update-version
$ codex app-server daemon restart
{"status":"restarted","pid":1223867,"appServerVersion":"0.160.0"}

$ ps -o args= -C codex | grep update-loop
... bin/codex app-server daemon pid-update-loop

این دیمون چه چیزی را برای راه دور نگه می‌دارد

دلیل وجود این دیمون، اجرای app-server روی ماشین‌هایی است که از بیرون به آن‌ها وصل می‌شوند. مستند رسمی اتصال‌های راه دور می‌گوید دسترسی راه دور از پروژه‌ها، گفتگوها، فایل‌ها، اعتبارنامه‌ها، مجوزها، پلاگین‌ها، Computer Use و ابزارهای محلیِ همان میزبان استفاده می‌کند، و فرمان‌های روی میزبان اجرا می‌شوند. یعنی دیمون فقط یک بهینه‌سازی سرعت نیست؛ همان چیزی است که کنترل از بیرون را ممکن می‌کند.

$ cat /root/.codex/app-server-daemon/settings.json
{
  "remoteControlEnabled": true
}

# تنظیمات کامل‌تری که مستند برای کنترل زمان‌بندی به‌روزرسانی می‌دهد
{
  "remoteControlEnabled": false,
  "shutdownGraceSeconds": 60,
  "updater": {"autoUpdateEnabled": false, "updateIntervalMinutes": 120}
}

مهلت خاموشی پیش‌فرض ۶۰ ثانیه است و عددی بین ۰ تا ۳۰۰ می‌پذیرد. مستند می‌گوید به‌روزرسانی‌های واجد شرایط پس از پنج دقیقه بررسی می‌کنند و بعد به‌صورت پیش‌فرض هر ساعت. همچنین همه‌ی فرمان‌های تغییردهنده‌ی چرخه‌ی کار به ازای هر CODEX_HOME یکی‌یکی می‌شوند، پس اجرای هم‌زمان دو فرمان lifecycle با هم مسابقه نمی‌دهد.

یک نکته‌ی عملی از همین مستند: کدکس از نام میزبان‌های مشخص در ~/.ssh/config استفاده می‌کند و آن‌ها را با OpenSSH حل می‌کند، اما میزبان‌هایی که فقط الگو هستند را نادیده می‌گیرد. روی یک سرور بدون ورود، یعنی همین موقعیت ما، مسیر درست برای pair کردن از سمت اپلیکیشن موبایل شروع می‌شود و از خط فرمان قابل انجام نیست. به همین دلیل در این آزمایش codex remote-control pair پیام داد که ثبت‌نام هنوز کامل نشده است، و چیزی درباره‌ی آن در این پست ادعا نمی‌شود.

قاعده‌ای که از این آزمایش بیرون آمد

اگر روی ماشینی که نسخه‌ی خط فرمانش از نسخه‌ی دیمون قدیمی‌تر است کار می‌کنید، اول codex app-server daemon version را بخوانید. وقتی دو عدد متفاوت دیدید، بدانید که این وضعیت خودبه‌خود درست می‌شود: حلقه‌ی خودکار به‌روزرسانی نسخه‌ی سرور را بالا می‌برد و اختلاف باقی نمی‌ماند. دست نزدنیدن به آن تنها زمانی معنی دارد که باید دقیقا نسخه‌ی خط فرمان روی سرور باشد، و آن زمان هزینه‌ی pin را هم بپذیرید.

# سه فرمان برای تشخیص وضعیت، همگی بدون نیاز به شبکه
$ codex --version
codex-cli 0.158.0
$ codex app-server daemon version
{"status":"running","backend":"pid","cliVersion":"0.158.0","appServerVersion":"0.160.0", ...}
$ ps -o args= -C codex | grep -c update-loop
1

سه عددی که اینجا دیده می‌شود وضعیت واقعی این سرور را در لحظه‌ی خواندن نشان می‌دهد: خط فرمان 0.158.0، سرور 0.160.0، و یک حلقه‌ی به‌روزرسانی فعال که فاصله را خودش می‌بندد. اگر آن عدد آخر صفر بود، یعنی pin انجام شده یا به‌روزرسانی خودکار خاموش است و باید دستی برگردید. جزئیات نسخه‌های دیگر در یادداشت‌های انتشار کدکس و مقایسه‌ی دو نسخه در گیت‌هاب آمده است، و فهرست فرمان‌های توسعه‌دهنده هم در مرجع فرمان‌ها است.

اگر تازه‌ترین نسخه‌ی منتشرشده را از پیش می‌خواهید، راه درست همان به‌روزرسانی کل فرمان است و نه دستکاری بسته‌ی دیمون: codex update و بسته‌ی npm را با هم جلو می‌برد. دست اندازیدن در پوشه‌ی packages/app-server-daemon تنها زمانی جواب می‌دهد که هر دو عدد باید برابر بمانند و بازگشت به تولید را خودتان با پیوند و ری‌استارت انجام می‌دهید.

منابع

  1. یادداشت انتشار Codex CLI 0.158.0 در گیت‌هاب؛ تاریخ انتشار و فهرست قابلیت‌ها، بازبینی: ۵ اکتبر ۲۰۲۶
  2. مستند دیمون app-server در همان نسخه‌ی 0.158.0؛ قرارداد JSON و قواعد pin، بازبینی: ۵ اکتبر ۲۰۲۶
  3. مستند دیمون app-server در نسخه‌ی 0.160.0؛ شرط کانال و تنظیمات به‌روزرسانی، بازبینی: ۵ اکتبر ۲۰۲۶
  4. مستند دیمون app-server روی شاخه‌ی main؛ رفتار فعلی پس از 0.160.0، بازبینی: ۵ اکتبر ۲۰۲۶
  5. اتصال‌های راه دور؛ آنچه از میزبان به دست می‌آید و مسیر pair کردن، بازبینی: ۵ اکتبر ۲۰۲۶
  6. یادداشت‌های انتشار ChatGPT و Codex؛ تاریخچه‌ی نسخه‌ها، بازبینی: ۵ اکتبر ۲۰۲۶
  7. صفحه‌ی بسته‌ی @openai/codex در npm؛ نسخه‌ی آخر 0.160.0، بازبینی: ۵ اکتبر ۲۰۲۶
  8. مقایسه‌ی نسخه‌های 0.157.0 تا 0.158.0 در گیت‌هاب؛ فهرست کامل تغییرات، بازبینی: ۵ اکتبر ۲۰۲۶
  9. مرجع فرمان‌های توسعه‌دهنده‌ی Codex؛ پرچم‌های سراسری و زیرفرمان‌ها، بازبینی: ۵ اکتبر ۲۰۲۶
  10. ساخت کلاینت ایجنت روی app-server کدکس؛ همان پروتکل JSON-RPC از زاویه‌ی کلاینت، برای ادامه‌ی همین بحث