HookStackGitHub
Back to catalogue
WorkflowWorktreeCreateWorktreeCreateOn worktree creation· non-blocking

Ghostty tab on worktree create

Hooks into WorktreeCreate to open a new Ghostty window pre-cd'd to the worktree path, so you can immediately run dev commands without navigating manually. macOS only. Silently skips if Ghostty is not installed.

Use cases

  • Open a dedicated terminal for each new worktree session
  • Speed up context-switching between parallel feature branches

Providers & tags

Claude Code
#worktree#ghostty#terminal#macos#dx

settings.json fragment

{
  "hooks": {
    "WorktreeCreate": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "node $CLAUDE_PROJECT_DIR/.claude/hooks/worktree-ghostty.mjs",
            "timeout": 10
          }
        ]
      }
    ]
  }
}

Script · .claude/hooks/worktree-ghostty.mjs

#!/usr/bin/env node
// Ouvre un nouvel onglet Ghostty sur le chemin du worktree créé (WorktreeCreate)
import { readFileSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';

function defaultExec(cmd) {
  execSync(cmd, { timeout: 10_000, stdio: 'ignore', shell: true });
}

export function run(input, { exec = defaultExec, platform = process.platform } = {}) {
  const worktreePath = input?.worktree_path;
  if (!worktreePath || platform !== 'darwin') return null;

  // WorktreeRemove n'a pas de champ branch — on n'ouvre rien dans ce cas
  const isCreate = Boolean(input?.branch);
  if (!isCreate) return null;

  try {
    exec(`ghostty --working-directory="${worktreePath}" &`);
  } catch {
    // Ghostty absent ou erreur — non bloquant
  }
  return null;
}

/* v8 ignore next 4 */
if (process.argv[1] === fileURLToPath(import.meta.url)) {
  const input = JSON.parse(readFileSync(0, 'utf8'));
  run(input);
}