OpenCode و PATH ناقص: چرا ابزارهای شما در شل نماینده نبودند؟
منتشر شده در 21 April 2026
شما OpenCode را در ترمینال خود اجرا میکنید؛ همه چیز به درستی کار میکند. عامل سعی میکند یک`gh`— یافت نشد. یک`java -version`— غایب. یک`node`— هیچجا. اما، این ابزارها واقعاً در votre شل موجود هستند. مشکل ؟ OpenCode 쉘ها را اجرا میکندغیر تعاملیکه هرگز شما را نمیخوانند`.zshrc`در اینجا روش تشخیص و رفع آن بهصورت مناسب را نشان میدهیم.
- فهرست محتويات
-
[]
صحنه : یک عامل کور در یک عالم ابزار
این یک شب سهشنبه بود. من تازه نصب کرده بودمhttps://opencode.ai[کد باز], الوكيل الذكي الاصطناعي الذي كان يعدّ بتحويل طريقة برمجتي. الاختبار الأول: أن أطلب منه أن يسرد مستودعاتي على جيت هاب.
$ opencode
> Utilise gh pour lister mes repos
❌ bash: gh: command not found
عجیب.`gh`در ترمینال من به خوبی کار میکرد. من چیز دیگری امتحان میکنم :
> Vérifie la version de Java
❌ bash: java: command not found
سپس:
> Lance le build Gradle
❌ bash: gradle: command not found
جاوا، گردل، نود،gh— همه چیز برای مامور نامرئی بود. ترمینال من، او هم، همه چیز را میدید. گویی مامور و من در دو جهان موازی زندگی میکردند.
من ساعتها را صرف فهمیدن کردم. ساعتهای`echo $PATH`, de which java, از narahati-ye afzayesh. من در نهایت متوجه شدم که مشکل ابزارها نبود — کهشل. OpenCode، مانند هر عاملی که زیرفرآیندها را راهاندازی میکند، در پوستهها کار میکندغیر تعاملی. و Zsh، در این شلها، به سادگی صرفاً`.zshrc`.
این متن زیر گزارش کامل از این تشخیص، حل، و درس است که از آن به دست آوردم. اگر از یک عامل هوش مصنوعی — OpenCode, Aider, Cursor یا حتی اسکریپتهای cron — استفاده میکنید، این مشکل يوماً به شما مربوط خواهد شد.
تشریح باگ: دو شل، دو جهان
وقتی یک ترمینال باز میکنید، Zsh آن را به عنوان یک شل محسوب میکندتعاملی. او بار میگیرد`.zshrc`، که همه چیز را مقداردهی میکند: SDKMAN, NVM, pnpm, الیاها، پرامپت زیبای شما. محیط شما کامل است.
اما وقتی OpenCode یک دستور را اجرا میکند، یک ترمینال تعاملی را راهاندازی نمیکند. یک شل را راهاندازی میکند.غیر تعاملی— یک شل وظیفهای، بدون انسان پشت صفحه. و Zsh، در این زمینه، میپرد`.zshrc`.او فقط میخواند`.zshenv`.
چرا این وجود دارد؟ چون شل غیرتعاملی برای اجرای اسکریپتها طراحی شده، نه برای خدمت به یک کاربر بشر. بارگذاری aliasها، prompt و تکمیلها در یک اسکریپتی که در پسزمینه اجرا میشود، هدر رفتن است. مشکل این است که PATH شما — اطلاعاتی که مهمترین برای یافتن اجراهای قابل اجرا است — غالبًا در`.zshrc`, نه در`.zshenv`.
@startuml skinparam backgroundColor #FEFEFE actor "شما" as user actor "OpenCode\n(عامل)" as agent participant "Shell تعاملی (.zshrc منبع شده)" as ishell participant "Shell\nغیر تعاملی\n(.zshrc نادیده)" as nshell user -> ishell : gh, java, node ✅ agent -> nshell : gh, java, node ❌ note right of ishell Source .zshrc : - SDKMAN init - NVM init - ~/apps dans PATH - pnpm dans PATH end note note right of nshell .zshrc ignoré ! PATH = /usr/bin:/bin + quelques répertoires défaut end note @enduml
ریشه مسئله :Zsh فقط برای شلهای تعاملی .zshrc را بارگذاری میکند. OpenCode، همانند هر عامل هوش مصنوعی که زیرفرآیندها را راهاندازی میکند، از شلهای غیر تعاملی استفاده میکند. این شلها فقط`.zshenv`.
متهمان: .zshrc در مقابل .zshenv
Zsh داردچهار فایل راهاندازی, هر کس با نقش دقیقی. این یک طراحی ظریف است — اما همین مشکل اصلی است:
فایل |
منبع شده وقتی |
نقش |
PATH را تغییر میدهی؟ |
|
همیشه(تعاملی + غیرتعاملی + login) |
متغیرهای محیطی ضروری، PATH |
✅ بله — این جای اوست |
|
شلهای ورود فقط |
دستورات آهسته (یک بار در هر جلسه) |
ممکن |
|
فقط پوستههای تعاونی |
Alias, prompt, تکمیل، ابزارهای تعاملی |
❌ برای متغیرهای بحرانی نیست |
|
شلهای ورود (پس از .zshrc) |
پیامهای خوشآمدگویی, نهاییسازی |
به ندرت |
جدول یک نشانه میدهد، اما باید آن را به عمق درک کرد. ان را همانند اتاقهای یک منزل در نظر بگیرید :
-
`.zshenv`استراهرو ورود— همه از اینجا عبور میکنند، مهمان یا مقیم. اگر چیزی اینجا بگذارید، هر شل میتواند آن را ببیند.
-
`.zshrc`استسالن— فقط ساکنان (shellهای تعاملی) وارد میشوند. مهمانان (shellهای غیرتعاملی) در بهو میمانند.
-
.zprofileet `.zlogin`هستند قطعات مخصوص برای شلهای ورود (مثل زمانی که از طریق SSH وارد میشوید).
مشكله این است که اکثر ما PATH را در اتاق نشیمن میگذاریم. و facteur IA، او هرگز اجازه ورود به آنجا را ندارد.
مشکل در یک نمودار:
@startuml
skinparam backgroundColor #FEFEFE
start
if (Shell interactif ?) then (Oui)
:Source .zshenv;
:Source .zprofile;
:Source .zshrc;
:Source .zlogin;
note right
SDKMAN ✅
NVM ✅
~/apps ✅
pnpm ✅
end note
else (Non — shell non-interactif)
:Source .zshenv uniquement;
note right
SDKMAN ❌
NVM ❌
~/apps ❌
pnpm ❌
end note
endif
stop
@enduml
وقتی که یک ترمینال باز میکنید، Zsh تعاملی است: آن را میخواند`.zshrc`, وقتی OpenCode یک شل را برای اجرای یک دستور اجرا میکند، Zsh غیرتعاملی است: او میپرد`.zshrc`, فقط میخواند`.zshenv`. Et si `.zshenv`موجود نیست یا PATH را حاوی نیست — این یک صحراست.
|
چرا Zsh این کار را انجام میدهد؟این یک گزینش طراحی به ارث رسیده از یونیکس است. یک شل غیر تعاملی باید باشدسریع et قابل بازتولید. بارگذاری aliasها، پرامپتهای رنگdar و مقداردهیهای سنگین SDKMAN در یک اسکریپت cron یا یک عامل AI کند و شکننده خواهد بود؛ بنابراین جدایی منطقی :`.zshenv`بهطور کلی (variables, PATH),`.zshrc`برای راحتی (aliases, prompt, کامل میکنیم). مشکل پیش میآید وقتی که مورد ضروری را در راحتی قرار میدهیم. |
تشخیص گام به گام
قبل از اصلاح، باید دقیقاً متوجه شویم چه چیزی کم است. یک روش تشخیص قابل تکرار — اگر با عوامل هوش مصنوعی کار میکنید، آن را در bookmarks/ favorites خود نگهدارید.
1. مسیر عامل را بررسی کنید
ما مقایسه میکنیم که ترمینال تعاملی شما چه میبیند، با اینکه چه میبیند یک شل غیر تعاملی — یعنی چه میبیند OpenCode.
# Dans votre terminal interactif (tout fonctionne)
echo $PATH | tr ':' '\n' | grep -v '^/usr' | sort
نتیجهٔ معمول :
/home/cheroliv/apps
/home/cheroliv/.nvm/versions/node/v22.19.0/bin
/home/cheroliv/.sdkman/candidates/java/current/bin
/home/cheroliv/.sdkman/candidates/gradle/current/bin
/home/cheroliv/.local/share/pnpm
/home/cheroliv/.local/bin
اکنون، بیایید شبیهسازی کنیم که چه چیزی عامل میبیند — یک شل غیر تعاملی:
# Shell non-interactif : pas de .zshrc
zsh -c 'echo $PATH' | tr ':' '\n' | grep -v '^/usr' | sort
نتیجه :
/home/cheroliv/.local/bin
پنج مسیر از شش مسیر غایب شدهاند.عامل به ۸۳٪ از محیط خود قطع شده است. دقیقاً همانطور که اگر از شما بخواهند بدون نیم ابزار آشپزیتان غذا پز کنید، فقط میتوانید آب را جوش دهید اما تقریباً چیزی دیگر نمیتوانید.
|
دستور`zsh -c 'echo $PATH'`است شماابزار تشخیص شماره 1. اگر ابزاری که روزانه استفاده میکنید در نتایج غایب باشد، عامل هوش مصنوعی شما نیز نمیتواند آن را ببیند. آن را قبل و پس از هر تغییر تست کنید. |
شناسایی آنچه در .zshrc است ولی در .zshenv نیست
اکنون ما به دنبال مسبب در`.zshrc`. ما خطوطی که ابزارهای ما را ذکر میکنند را فیلتر میکنیم:
grep -n 'apps\|SDKMAN\|NVM\|PNPM\|PATH' ~/.zshrc
به طور معمول مشاهده میشود:
119: PATH="/usr/bin/python3:$HOME/apps:$PATH" # ← pas exporté !
171: export NVM_DIR="$HOME/.nvm"
172: [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # ← NVM init
176: nvm use --lts --silent # ← active une version
179: export PNPM_HOME="/home/cheroliv/.local/share/pnpm"
187: export SDKMAN_DIR="$HOME/.sdkman"
188: [[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
همه این استناتوان دیده میشودبرای OpenCode. و`PATH`حتی خط 119 نیست`export`é — او هرگز از شل جاری خارج نمیشود. این یک جزئی فنی حیاتی است : یک متغیر بدون`export`در شالی که آن را تعریف میکند، محلی باقی میماند. زیرشِلها — همانگونه که توسط OpenCode اجرا میشوند — هرگز آن را به ارث نمیبرند.
3. بررسی کنید که آیا .zshenv وجود دارد
cat ~/.zshenv 2>/dev/null || echo "FICHIER ABSENT"
اگر پاسخ « فایل گمشده » باشد، همانجا است که همه چیز تعیین میشود.
حل : .zshenv + مسیرهای صحیح
استراتژی ساده است، اما نیاز به دقت دارد: قرار دادن در`.zshenv` فقطمسارات ضروری، بدون بارگذاری اسکریپتهای راهاندازی سنگین. ما آن را جابجا نمیکنیم..zshrc`در.zshenv`— ما جوهر را استخراج میکنیم.
ایجاد .zshenv با تمام مسیرهای ضروری
`.zshenv`استفایل تنهاکه Zsh تضمین میکند که source کند درهمهمحیطها. اینجاست که PATH باید برود.
export SDKMAN_DIR="$HOME/.sdkman"
export NVM_DIR="$HOME/.nvm"
export PNPM_HOME="$HOME/.local/share/pnpm"
export PATH="$HOME/apps:$HOME/.sdkman/candidates/java/current/bin:$HOME/.sdkman/candidates/gradle/current/bin:$HOME/.nvm/current/bin:$PNPM_HOME:$HOME/.local/bin:$HOME/.local/share/JetBrains/Toolbox/scripts:/usr/bin/python3:$PATH"
|
استفاده میشود`$HOME/.nvm/current/bin`و نه`$HOME/.nvm/versions/node/v22.19.0/bin`. دلیل: نسخههای Node تغییر میکنند. یک مسیر ثابت در نسخه بعدی اشتباه میشود. |
چرا نه source sdkman-init.sh در .zshenv ؟
راهبرد بیشترین ترغیب این است که به سادگی آن را در`.zshenv`ما که در آن انجام میدهیم`.zshrc`— منبع کردن اسکریپتهای راهاندازی. مامیتوانستبه وسواس افتاده برای انجام :
# ❌ MAUVAISE IDÉE
[[ -s "$HOME/.sdkman/bin/sdkman-init.sh" ]] && source "$HOME/.sdkman/bin/sdkman-init.sh"
مشکلات :
-
آواژ:`sdkman-init.sh`او در هر شل، حل شبکه و بررسیهای لازم را انجام میدهد. در یک شل غیر تعاملی، این هزینه بیضروری است.
-
شکستنیSDKMAN انتظار دارد که در یک محیط تعاملی باشد. مقداردهی اولیه آن ممکن است بهصورت ساکت در یک لول (pipe) یا زیرشل (subshell) شکست بخورد.
-
بیفایده: SDKMAN نامزدهای خود را در`~/.sdkman/candidates/<tool>/current/bin`— symlinks ثابت که به نسخه فعال اشاره دارند. میتوانیم از آنها استفاده کنیممستقیم.
روش مناسب: دور زدن مقداردهی اولیه SDKMAN و اشاره مستقیم به پیوندهای سمبولیک`current`. این کلید تمام راهحل است :استفاده از ساختار فایل بهعنوان قرارداد، به جای کد راهاندازی.
@startuml
skinparam backgroundColor #FEFEFE
rectangle "روشی آهسته\n(source sdkman-init.sh)" as slow {
card ".zshenv source sdkman-init.sh
2-3 ثانیه برای هر پوسته
بررسیهای شبکه
خطر شکست" as s1 #FDEDEC
}
rectangle "رویکرد سریع
(پیوندهای سمبولیک مستقیم)" as fast {
card ".zshenv export PATH=...current/bin
0 ms
بدون شبکه
بدون مقداردهی اولیه" as s2 #E8F8E8
}
slow --> fast : Même résultat final\nLe PATH pointe sur current/bin\ndans les deux cas
@enduml
مورد NVM: زمانی که مدیر نسخها فراموش میکند یک اثر بگذار
مشکل NVM
اینجا است که تحقیق مرا تا بیشترین مسافت برد. SDKMAN یک طراحی شیک دارد : وقتی که`sdk install java 25.0.2-tem`, او یک symlink ایجاد میکند :
~/.sdkman/candidates/java/current -> ~/.sdkman/candidates/java/25.0.2-tem
این symlink استهمیشه بهروز. señalدهیدrouille annotations در`.zshenv`و شما محافظت شدهاید، چه شل که باشد. عالی.
NVM، او، نه میسازدهیچ چیزچنین. هیچ symlink`current`. نقطهٔ پایداری ثابتی وجود ندارد. باید به یک مسیر نسخهبندیشدهی سخت‑کد اشاره کرد، که شبیه به این است:
~/.nvm/versions/node/v22.19.0/bin/node
به بعدی`nvm install 24`, این مسیر مرده است. شما`.zshenv`به یک نسخه که دیگر نسخة فعال نیست، اشاره خواهد کرد. این یک بمب موقوت است.
|
چرا NVM این کار را میکند؟NVM با تغییر بهصورت دینامیک PATH در هر`nvm use`. این برای توسعهدهندههایی که نسخ را بهصورت منظم تغییر میدهند، در یک شل تعاملی طراحی شده است. لینک سمبولی`current`در مشخصات اولیه وجود نداشته بود — یک اشتباه طراحی که خودمان آن را برطرف میکنیم. |
@startuml
skinparam backgroundColor #FEFEFE
package "SDKMAN ✅" {
[~/.sdkman/candidates/java/current] as sdk_current
[~/.sdkman/candidates/java/25.0.2-tem/] as java_25
[~/.sdkman/candidates/java/21.0.7-tem/] as java_21
sdk_current --> java_25 : symlink
}
package "NVM ❌ (قبل از اصلاح)" as nvm_before {
[~/.nvm/versions/node/v22.19.0/] as node_22
[~/.nvm/versions/node/v20.16.0/] as node_20
note right of node_22
Pas de symlink current !
.zshenv doit pointer en dur
Cassé au prochain nvm install
end note
}
package "NVM ✅ (پس از اصلاح)" as nvm_after {
[~/.nvm/current] as nvm_current
[~/.nvm/versions/node/v22.19.0/] as node_22b
[~/.nvm/versions/node/v20.16.0/] as node_20b
nvm_current --> node_22b : symlink\n(mis à jour auto)
}
@enduml
راهحل: ایجاد symlink current برای NVM
از آنجا که NVM این کار را انجام نمیدهد، ما خودمان این کار را انجام میدهیم. اصل آن همان SDKMAN است — یک symlink`current`همیشه به نسخه فعال اشاره دارد. ما آن را یک بار میسازیم و سپس آن را خودکار میکنیم تا خود به خود بهروز شود.
# Créer le symlink initial
ln -sfn "$HOME/.nvm/versions/node/v22.19.0" "$HOME/.nvm/current"
اکنون، در`.zshenv`، از استفاده میکنیم :
$HOME/.nvm/current/bin
به جای :
# ❌ Chemin en dur — cassé au prochain changement de version
$HOME/.nvm/versions/node/v22.19.0/bin
بهروزرسانی symlink را خودکار کن
یک symlink ارزش ندارد اگر بهروزرسانی نشود. symlink`current`باید بهروز شود وقتی که انجام میدهد`nvm use` ou nvm install. راهحل: یکپوشش— یک تابع که دستور واقعی را در بر میگیرد`nvm`و سمبلینک را پس از هر فراخوانی بهروزرسانی میکند.
# À la fin de .zshrc, APRÈS le chargement de NVM
nvm use --lts --silent
ln -sfn "$(nvm_version_path "$(nvm current)")" "$NVM_DIR/current"
_nvm() {
command nvm "$@"
local rc=$?
ln -sfn "$(nvm_version_path "$(nvm current)")" "$NVM_DIR/current"
return $rc
}
alias nvm='_nvm'
چگونه کار میکند، به صورت جزئی:
@startuml skinparam backgroundColor #FEFEFE actor Développeur participant "nvm wrapper (_nvm)" as wrapper participant "nvm réel\n(command nvm)" as realnvm participant "~/.nvm/current\n(symlink)" as symlink Développeur -> wrapper : nvm use 20 wrapper -> realnvm : command nvm use 20 realnvm --> wrapper : version activée wrapper -> symlink : ln -sfn .../v20.16.0 ~/.nvm/current wrapper --> Développeur : retour note right of symlink Toujours à jour ! Utilisé par .zshenv → accessible par OpenCode end note @enduml
بستهبندی`_nvm`دستور واقعی فراخوانی میکند`nvm`, سپس symlink را بهروزرسانی می-conduct. alias`nvm='_nvm'`به گونهای که هنگام تایپ`nvm`, از طریق wrapper میرویم. و هنگام مقداردهی اولیه شل، نیز همین کار را بعد انجام میدهیم.nvm use --lts.
|
`nvm_version_path`یک تابع داخلی NVM است که مسیر کامل یک نسخه را حل میکند. این کار نیاز به بازسازی دستی مسیر را از بین میبرد. |
جدول خلاصه مسیرها
قبل از رفتن به دامها، یک خلاصه بصری از تبدیل. در سمت چپ، چه چیزی که داشتید (همه در`.zshrc`, برای عامل نامرئی). در سمت راست، چه چیزی الآن دارید (مسارات ضروری در`.zshenv`, در هم�؟
| ابزار | قبل (.zshrc فقط) | بعد از (.zshenv + symlink) | قابل مشاهده توسط OpenCode؟ |
|---|---|---|---|
|
PATH صادر نشده در .zshrc |
`$HOME/apps`در .zshenv |
(Empty) |
SDKMAN Java |
`sdkman-init.sh`منبع در .zshrc |
`$HOME/.sdkman/candidates/java/current/bin`در .zshenv |
✅ |
SDKMAN Gradle |
`sdkman-init.sh`منبع در .zshrc |
`$HOME/.sdkman/candidates/gradle/current/bin`در .zshenv |
✅ |
NVM نود |
`nvm use --lts`در .zshrc |
`$HOME/.nvm/current/bin`در .zshenv (symlink) |
(Empty output) |
pnpm |
`$PNPM_HOME`در .zshrc |
`$PNPM_HOME`در .zshenv |
✅ |
JetBrains Toolbox |
بهصورت خودکار توسط Toolbox در .zshrc افزوده شد |
`$HOME/.local/share/JetBrains/Toolbox/scripts`در .zshenv |
✅ |
پایتون ۳ |
`/usr/bin/python3`در PATH .zshrc |
بهطور صریح در .zshenv |
✅ |
موانع و تدابیر کاهش
همه چیز با این رویکرد کامل نیست. این مشکلاتی هستند که با آنها مواجه شدم و چگونگی رفع کردنشان.
| فخ | توضیحات | کاهش |
|---|---|---|
PATH تکراری |
اگر .zshenv و .zshrc همان مسیر را اضافه کنند، دو بار نمایش داده میشود |
`.zshenv`منبعگذاری شدهقبل.zshrc. هر دو در یک shell تعاملی خوانده میشوند. PATH میتواند تکراری شود. این فقط ظاهری است، نه عملکردی. برای جلوگیری از این: فقط مسیرهایی که در PATH پیشفرض غایب هستند را در .zshenv قرار دهید. |
NVM : نسخهی ثابت در .zshenv |
گذاشتن`~/.nvm/versions/node/v22.19.0/bin`در سخت، در بعدی نادرست میشود`nvm install` |
از symlink استفاده کن`$HOME/.nvm/current/bin`+ بسته`_nvm`در .zshrc |
SDKMAN : source sdkman-init.sh در .zshenv |
avaş، شکننده، بیفایده در یک شل غیر تعاملی |
استفاده از لینکهای نمادین`candidates/<tool>/current/bin`مستقیم |
Alias گمشده پس از تغییر |
بسته`nvm='_nvm'`در .zshrc فقط پس از بارگذاری مجدد اثر میگیرد |
شِل را دوباره راهاندازی کنید یا`source ~/.zshrc` |
OpenCode تغییرات را نمیبیند. |
عامل قبلاً شلهای فرعی خود را با .zshenv قدیمی راهاندازی کرده |
OpenCode را پس از تغییر .zshenv دوباره راهاندازی کنید |
.zshenv بسیار بارگذاری شده |
قرار دادن توابع سنگین یا اولیهسازیهای تعاملی در .zshenv |
.zshenv = متغیرهای محیط + PATH فقط. ندارد`source`, بدون توابع سنگین، بدون پرامپت. |
دروس آموختگی
-
.zshrc` تعاملی است،
.zshenvسراسری است— اگر یک متغیر باید در تمام شلها (aktoren هوش مصنوعی، cron، اسکریپتها، IDE) وجود داشته باشد، آن در`.zshenv`.سالن راحتمند است، اما ورودی تنها مکانی است که همه از آن میگذرند. -
مدیران نسخهها برابر نیستند— SDKMAN لینکهای sembولی ایجاد میکند`current`به صورت طراحی. NVM نه. باید این نقص را به صورت دستی جبران کرد. این یک درس مهم است: قبل از تنظیم PATH خود، بررسی کنید که آیا مدیریت شما یک نقطهٔ تثبيت ثابت ارائه میدهد؟
-
اسکریپتهای init را در .zshenv سورس نکنید—
sdkman-init.shet `nvm.sh`برای یک شل تعاملی طراحی شدهاند. در زمینه غیرتعاملی، آهسته و شکنندهاند. ارتباطات نمادین`current`کافی هستند و فوری هستند. -
همیشه در شل غیر تعاملی تست کنید—`zsh -c 'echo $PATH'`دقیقاً همان چیزی که یک نماینده میبیند را شبیهسازی میکند. این تست اعتبارسنجی است. بدون این تست، نمیدانید آیا پیکربندی شما برای نمایندگان کار میکند یا نه.
-
الگوی wrapper قابل استفاده دوباره است— الگو یکسان`_nvm`+`alias nvm='_nvm'`این به هر ابزارهایی که PATH را بهصورت دینامیک تغییر میدهند و اثر پایداری باقی نمیگذارند، اعمال میشود. این یک ابزار دیگر در جعبه ایدههای شما است.
@startuml
skinparam backgroundColor #FEFEFE
rectangle "قبل" as avant {
card "Shell تعاملی : ✅
Shell غیر تعاملی : ❌
OpenCode : ❌
Cron : ❌
Scripts : ❌" as av1 #FDEDEC
}
rectangle "پس از" as apres {
card "Shell تعاملی : ✅
Shell غیرتعاملی : ✅
OpenCode : ✅
Cron : ✅
اسکریپتها : ✅" as ap1 #E8F8E8
}
avant --> apres : .zshenv +\nsymlink ~/.nvm/current
@enduml
بررسی نهایی
پس از ایجاد`.zshenv`و symlink NVM، اطمینان حاصل کنید که همه چیز کار میکند — در هر دو زمینه :
# Shell interactif (votre terminal)
gh --version && java -version && node --version
# Shell non-interactif (simulation OpenCode)
zsh -c 'gh --version && java -version && node --version'
هر دو باید موفق شوند. اگر بله، عامل هوش مصنوعی شما همان ابزارهایی را که شما دارید، میبیند. اگر خیر، به تشخیص قدم به قدم بازگردید — احتمالاً یک مسیر را فراموش کردهاید یا symlink NVM بهروز نیست.
|
این تست را خودکار کنید.این بررسی را در یک اسکریپت healthcheck که پس از هر بروزرسانی ابزارهای خود را اجرا میکنید، اضافه کنید. یک`zsh -c 'which java && which node && which gh'`در CI، یک ضمانت در برابر شگفتیها است. |
_ یک شل غیر تعاملی مثل یک مهمان ساکت است: او فقط چیزی را میخواند که در در ورودی نمایش داده شود. اگر PATH در اتاق نشیمن باشد، او آن را هرگز نخواهد دید. _
لینکها
مستندات رسمی
-
Zsh اسناد : فایلهای راهاندازی— مرجع رسمی درباره فایلهای راهاندازی Zsh. جایی که همه چیز توضیح داده میشود، حتی اگر اغلب فراموش میشود.
-
OpenCode : تنظیماتراهنمای تنظیم OpenCode و محیط اجرایی آن
ابزارهای ذکر شده
-
NVM در گیتهاب— Node Version Manager. مدیر نسخههای Node.js.
-
SDKMAN — سایت رسمی— SDKMAN! مدیریت نسخهها برای JVM (Java, Kotlin, Gradle…)
-
SDKMAN : نصب— راهنمای نصب SDKMAN.
-
gh` — خط فرمان GitHub— ابزار خط فرمان GitHub، ضروری برای هر توسعهدهنده
-
Gradle — سایت رسمی— سیستم ساخت که ما آن را از طریق SDKMAN نصب میکنیم.
-
pnpm — سایت رسمی— مدیر بستههای Node.js سریع وصرفهجویی در فضا
-
JetBrains Toolbox— مدیر IDE JetBrains، که اسکریپتهای خود را به PATH اضافه میکند.
برای پیش رفتن بیشتر
-
Zsh dotfiles: راهنمای کامل— مقاله جامع درباره مدیریت dotfiles Zsh
-
Zsh در ArchWiki— یکی از بهترین مستندات جامعهای در مورد Zsh.
-
مشکلات NVM GitHub— برای دیدن مباحث پیرامون symlink`current`و مشکلات PATH