رفتن به محتوا

اجرای نشست‌های موازی با worktree

git worktree یک شاخه‌کاریِ جدا با فایل‌ها و شاخه‌ی مخصوصِ خودش است که تاریخچه و remoteِ مخزن را با چک‌اوتِ اصلی‌ات به اشتراک می‌گذارد. اجرای هر نشستِ Claude Code در worktreeِ خودش یعنی ویرایش‌ها در یک نشست هرگز فایل‌های نشستِ دیگر را دست نمی‌زنند؛ پس می‌توانی در یک ترمینال Claude را به ساختِ یک قابلیت بگماری و در ترمینالِ دوم به رفعِ یک باگ.

این صفحه isolationِ worktree را در CLI پوشش می‌دهد. هر چیزی که در ادامه می‌آید یک مخزنِ git را فرض می‌گیرد. برای دیگر سیستم‌های کنترلِ نسخه، کنترلِ نسخه‌ی غیرِ git را ببین. اپلیکیشنِ دسکتاپ برای هر نشستِ جدید به‌صورت خودکار یک worktree می‌سازد.

worktreeها یکی از چند راهِ اجرای موازیِ Claude هستند. آن‌ها ویرایشِ فایل‌ها را جدا می‌کنند، در حالی که ساب‌ایجنت‌ها و تیم‌های ایجنت خودِ کار را هماهنگ می‌کنند. برای مقایسه‌ی این رویکردها اجرای موازیِ ایجنت‌ها را ببین، یا مستقیم برو به جداسازیِ ساب‌ایجنت‌ها با worktree تا worktree و ساب‌ایجنت را با هم به کار ببری.

Claude را در یک worktree راه بینداز

Section titled “Claude را در یک worktree راه بینداز”

با پاس‌دادنِ --worktree یا -w یک worktreeِ جدا بساز و Claude را در آن راه‌اندازی کن. به‌صورت پیش‌فرض، worktree زیرِ .claude/worktrees/<value>/ در ریشه‌ی مخزن ساخته می‌شود، روی شاخه‌ی جدیدی به نامِ worktree-<value>:

Terminal window
claude --worktree feature-auth

برای قراردادنِ worktreeها در جایی دیگر، یک هوکِ WorktreeCreate تنظیم کن. همان دستور را با نامی دیگر در ترمینالِ دیگری اجرا کن تا نشستِ جدا و دومی شروع شود:

Terminal window
claude --worktree bugfix-123

اگر نام را حذف کنی، Claude خودش یکی مثلِ bright-running-fox می‌سازد:

Terminal window
claude --worktree

می‌توانی در میانِ یک نشست هم از Claude بخواهی «در یک worktree کار کن»، و او با ابزارِ EnterWorktree یکی می‌سازد. وقتی در یک worktree هستی، Claude می‌تواند با فراخواندنِ EnterWorktree با مسیرِ مقصد، مستقیم به worktreeِ دیگری زیرِ .claude/worktrees/ سوییچ کند. worktreeِ قبلی دست‌نخورده روی دیسک می‌ماند.

پیش از استفاده‌ی تعاملی از --worktree در یک دایرکتوری برای اولین بار، با اجرای یک‌باره‌ی claude در آن دایرکتوری دیالوگِ اعتمادِ workspace را بپذیر. اگر اعتماد هنوز پذیرفته نشده باشد، --worktree با خطا خارج می‌شود و از تو می‌خواهد اول claude را در دایرکتوری اجرا کنی. اجراهای غیرِتعاملی با -p از بررسیِ اعتماد رد می‌شوند، پس claude -p --worktree بدونِ آن پیش می‌رود.

شاخه‌ی پایه را انتخاب کن

Section titled “شاخه‌ی پایه را انتخاب کن”

worktreeها از شاخه‌ی پیش‌فرضِ مخزنت، یعنی origin/HEAD، شاخه می‌گیرند، پس از یک درختِ تمیز که با remote مطابقت دارد شروع می‌شوند. اگر هیچ remoteی تنظیم نشده باشد یا fetch شکست بخورد، worktree به HEADِ محلیِ فعلی‌ات برمی‌گردد. برای اینکه همیشه از HEADِ محلی شاخه بگیری، worktree.baseRef را در تنظیمات روی "head" بگذار. تنظیمِ baseRef روی "head" باعث می‌شود worktreeهای جدید کامیت‌های push‌نشده و وضعیتِ شاخه‌ی قابلیتت را با خود ببرند، که هنگامِ جداسازیِ ساب‌ایجنت‌هایی که باید روی کارِ در حالِ انجام عمل کنند مفید است. این تنظیم فقط "fresh" یا "head" را می‌پذیرد، نه refهای دلخواهِ git:

{
"worktree": {
"baseRef": "head"
}
}

برای شاخه‌گرفتن از یک pull request مشخص، شماره‌ی PR را با پیشوندِ # پاس بده، یا یک URLِ کاملِ pull requestِ GitHub. Claude Code شاخه‌ی pull/<number>/head را از origin می‌گیرد و worktree را در .claude/worktrees/pr-<number> می‌سازد:

Terminal window
claude --worktree "#1234"

برای کنترلِ کاملِ نحوه‌ی ساختِ worktreeها، یک هوکِ WorktreeCreate تنظیم کن که منطقِ پیش‌فرضِ git worktree را کاملاً جایگزین می‌کند.

کپی‌کردنِ فایل‌های gitignore‌شده در worktreeها

Section titled “کپی‌کردنِ فایل‌های gitignore‌شده در worktreeها”

یک worktree یک چک‌اوتِ تازه است، پس فایل‌های ردیابی‌نشده مثلِ .env یا .env.local از مخزنِ اصلی‌ات حاضر نیستند. برای کپیِ خودکارِ آن‌ها وقتی Claude یک worktree می‌سازد، یک فایلِ .worktreeinclude به ریشه‌ی پروژه‌ات اضافه کن.

این فایل از سینتکسِ .gitignore استفاده می‌کند. فقط فایل‌هایی که با یک الگو مطابقت دارند و همچنین gitignore‌شده‌اند کپی می‌شوند، پس فایل‌های ردیابی‌شده هرگز تکرار نمی‌شوند.

این .worktreeinclude دو فایلِ env و یک فایلِ پیکربندیِ secrets را در هر worktreeِ جدید کپی می‌کند:

.env
.env.local
config/secrets.json

این روی worktreeهای ساخته‌شده با --worktree، worktreeهای ساب‌ایجنت، و نشست‌های موازی در اپلیکیشنِ دسکتاپ اعمال می‌شود.

جداسازیِ ساب‌ایجنت‌ها با worktree

Section titled “جداسازیِ ساب‌ایجنت‌ها با worktree”

ساب‌ایجنت‌ها می‌توانند در worktreeهای خودشان اجرا شوند تا ویرایش‌های موازی با هم تداخل نکنند. از Claude بخواه «برای ایجنت‌هایت از worktree استفاده کن»، یا آن را به‌صورتِ دائمی روی یک ساب‌ایجنتِ سفارشی تنظیم کن، با افزودنِ isolation: worktree به frontmatter. هر ساب‌ایجنت یک worktreeِ موقت می‌گیرد که وقتی ساب‌ایجنت بدونِ تغییر تمام می‌شود به‌صورتِ خودکار حذف می‌شود.

worktreeهای ساب‌ایجنت از همان شاخه‌ی پایه‌ی --worktree استفاده می‌کنند، پس از شاخه‌ی پیش‌فرضِ مخزنت شاخه می‌گیرند، مگر اینکه worktree.baseRef روی "head" تنظیم شده باشد.

وقتی از یک نشستِ worktree خارج می‌شوی، پاک‌سازی بستگی به این دارد که آیا تغییری ایجاد کرده‌ای:

  • بدونِ تغییرِ کامیت‌نشده، بدونِ فایلِ ردیابی‌نشده، و بدونِ کامیتِ جدید: worktree و شاخه‌اش به‌صورتِ خودکار حذف می‌شوند. اگر نشست یک نام داشته باشد، Claude به‌جایش از تو می‌پرسد تا بتوانی worktree را برای بعد نگه داری
  • تغییرِ کامیت‌نشده، فایلِ ردیابی‌نشده، یا کامیتِ جدید وجود دارد: Claude از تو می‌پرسد که worktree را نگه داری یا حذف کنی. نگه‌داشتن دایرکتوری و شاخه را حفظ می‌کند تا بعداً برگردی. حذف، دایرکتوریِ worktree و شاخه‌اش را پاک می‌کند و هر تغییرِ کامیت‌نشده، فایلِ ردیابی‌نشده و کامیت را دور می‌اندازد
  • اجراهای غیرِتعاملی: worktreeهای ساخته‌شده با --worktree در کنارِ -p به‌صورتِ خودکار پاک نمی‌شوند، چون پرسشِ خروجی‌ای وجود ندارد. آن‌ها را با git worktree remove حذف کن

worktreeهایی که Claude برای ساب‌ایجنت‌ها و نشست‌های پس‌زمینه ساخته، به‌محضِ اینکه از تنظیمِ cleanupPeriodDaysات قدیمی‌تر شوند به‌صورتِ خودکار حذف می‌شوند، به‌شرطی که هیچ تغییرِ کامیت‌نشده، فایلِ ردیابی‌نشده، و کامیتِ push‌نشده‌ای نداشته باشند. worktreeهایی که خودت با --worktree می‌سازی هرگز با این جاروب حذف نمی‌شوند.

وقتی یک ایجنت در حالِ اجراست، Claude روی worktreeِ آن git worktree lock را اجرا می‌کند تا پاک‌سازیِ هم‌زمان نتواند آن را حذف کند. قفل وقتی ایجنت تمام می‌شود آزاد می‌شود. برای پاک‌سازیِ worktreeای که جاروب نگهش می‌دارد، git worktree remove را اجرا کن و اگر worktree تغییرِ کامیت‌نشده یا فایلِ ردیابی‌نشده دارد --force را هم اضافه کن.

برای کنترلِ کاملِ محلِ worktree و پیکربندیِ شاخه، worktreeها را مستقیماً با Git بساز. این وقتی مفید است که نیاز داری یک شاخه‌ی موجودِ مشخص را چک‌اوت کنی یا worktree را بیرونِ مخزن قرار دهی.

ساختِ worktree روی یک شاخه‌ی جدید:

Terminal window
git worktree add ../project-feature-a -b feature-a

ساختِ worktree از یک شاخه‌ی موجود:

Terminal window
git worktree add ../project-bugfix bugfix-123

راه‌اندازیِ Claude در worktree:

Terminal window
cd ../project-feature-a && claude

فهرست‌کردنِ worktreeهایت:

Terminal window
git worktree list

حذفِ یکی وقتی کارت با آن تمام شد:

Terminal window
git worktree remove ../project-feature-a

برای مرجعِ کاملِ دستورها مستنداتِ Git worktree را ببین. یادت باشد محیطِ توسعه‌ات را در هر worktreeِ جدید مقداردهیِ اولیه کنی: وابستگی‌ها را نصب کن، محیط‌های مجازی را راه بینداز، یا هر چه راه‌اندازیِ پروژه‌ات لازم دارد اجرا کن.

جداسازیِ worktree به‌صورتِ پیش‌فرض از git استفاده می‌کند. برای SVN، Perforce، Mercurial، یا دیگر سیستم‌ها، هوک‌های WorktreeCreate و WorktreeRemove را تنظیم کن تا منطقِ سفارشیِ ساخت و پاک‌سازی فراهم شود. چون هوک رفتارِ پیش‌فرضِ git را جایگزین می‌کند، وقتی از --worktree استفاده می‌کنی .worktreeinclude پردازش نمی‌شود. هر فایلِ پیکربندیِ محلی را به‌جایش داخلِ اسکریپتِ هوکت کپی کن.

این هوکِ WorktreeCreate نامِ worktree را از stdin می‌خواند، یک نسخه‌کاریِ تازه‌ی SVN چک‌اوت می‌کند، و مسیرِ دایرکتوری را چاپ می‌کند تا Claude Code بتواند آن را به‌عنوانِ دایرکتوریِ کاریِ نشست به کار ببرد:

{
"hooks": {
"WorktreeCreate": [
{
"hooks": [
{
"type": "command",
"command": "bash -c 'NAME=$(jq -r .name); DIR=\"$HOME/.claude/worktrees/$NAME\"; svn checkout https://svn.example.com/repo/trunk \"$DIR\" >&2 && echo \"$DIR\"'"
}
]
}
]
}
}

آن را با یک هوکِ WorktreeRemove جفت کن تا وقتی نشست تمام می‌شود پاک‌سازی شود. برای اسکیمای ورودی و یک نمونه‌ی حذف، مرجعِ هوک‌ها را ببین.

worktreeها جداسازیِ فایل را مدیریت می‌کنند. صفحه‌های مرتبطِ زیر واگذاریِ کار به آن چک‌اوت‌های جداشده و سوییچ بینِ نشست‌هایی که می‌سازی را پوشش می‌دهند: