MCPcopy Create free account
hub / github.com/AnukarOP/claude-code-leaked / performPostCreationSetup

Function performPostCreationSetup

source code/utils/worktree.ts:512–626  ·  view source on GitHub ↗

* Post-creation setup for a newly created worktree. * Propagates settings.local.json, configures git hooks, and symlinks directories.

(
  repoRoot: string,
  worktreePath: string,
)

Source from the content-addressed store, hash-verified

510 * Propagates settings.local.json, configures git hooks, and symlinks directories.
511 */
512async function performPostCreationSetup(
513 repoRoot: string,
514 worktreePath: string,
515): Promise<void> {
516 // Copy settings.local.json to the worktree's .claude directory
517 // This propagates local settings (which may contain secrets) to the worktree
518 const localSettingsRelativePath =
519 getRelativeSettingsFilePathForSource('localSettings')
520 const sourceSettingsLocal = join(repoRoot, localSettingsRelativePath)
521 try {
522 const destSettingsLocal = join(worktreePath, localSettingsRelativePath)
523 await mkdirRecursive(dirname(destSettingsLocal))
524 await copyFile(sourceSettingsLocal, destSettingsLocal)
525 logForDebugging(
526 `Copied settings.local.json to worktree: ${destSettingsLocal}`,
527 )
528 } catch (e: unknown) {
529 const code = getErrnoCode(e)
530 if (code !== 'ENOENT') {
531 logForDebugging(
532 `Failed to copy settings.local.json: ${(e as Error).message}`,
533 { level: 'warn' },
534 )
535 }
536 }
537
538 // Configure the worktree to use hooks from the main repository
539 // This solves issues with .husky and other git hooks that use relative paths
540 const huskyPath = join(repoRoot, '.husky')
541 const gitHooksPath = join(repoRoot, '.git', 'hooks')
542 let hooksPath: string | null = null
543 for (const candidatePath of [huskyPath, gitHooksPath]) {
544 try {
545 const s = await stat(candidatePath)
546 if (s.isDirectory()) {
547 hooksPath = candidatePath
548 break
549 }
550 } catch {
551 // Path doesn't exist or can't be accessed
552 }
553 }
554 if (hooksPath) {
555 // `git config` (no --worktree flag) writes to the main repo's .git/config,
556 // shared by all worktrees. Once set, every subsequent worktree create is a
557 // no-op — skip the subprocess (~14ms spawn) when the value already matches.
558 const gitDir = await resolveGitDir(repoRoot)
559 const configDir = gitDir ? ((await getCommonDir(gitDir)) ?? gitDir) : null
560 const existing = configDir
561 ? await parseGitConfigValue(configDir, 'core', null, 'hooksPath')
562 : null
563 if (existing !== hooksPath) {
564 const { code: configCode, stderr: configError } =
565 await execFileNoThrowWithCwd(
566 gitExe(),
567 ['config', 'core.hooksPath', hooksPath],
568 { cwd: worktreePath },
569 )

Callers 3

createWorktreeForSessionFunction · 0.85
createAgentWorktreeFunction · 0.85
execIntoTmuxWorktreeFunction · 0.85

Calls 12

mkdirRecursiveFunction · 0.85
logForDebuggingFunction · 0.85
getErrnoCodeFunction · 0.85
statFunction · 0.85
resolveGitDirFunction · 0.85
getCommonDirFunction · 0.85
parseGitConfigValueFunction · 0.85
execFileNoThrowWithCwdFunction · 0.85
getInitialSettingsFunction · 0.85
symlinkDirectoriesFunction · 0.85
copyWorktreeIncludeFilesFunction · 0.85

Tested by

no test coverage detected