@aku11i/phantom 0.1.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/bin/phantom.ts", "../src/commands/exec.ts", "../src/gardens/commands/where.ts", "../src/git/libs/get-git-root.ts", "../src/commands/shell.ts", "../src/gardens/commands/create.ts", "../src/git/libs/add-worktree.ts", "../src/gardens/commands/delete.ts", "../src/gardens/commands/list.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\n\nimport { argv, exit } from \"node:process\";\nimport { execHandler } from \"../commands/exec.ts\";\nimport { shellHandler } from \"../commands/shell.ts\";\nimport { gardensCreateHandler } from \"../gardens/commands/create.ts\";\nimport { gardensDeleteHandler } from \"../gardens/commands/delete.ts\";\nimport { gardensListHandler } from \"../gardens/commands/list.ts\";\nimport { gardensWhereHandler } from \"../gardens/commands/where.ts\";\n\ninterface Command {\n name: string;\n description: string;\n subcommands?: Command[];\n handler?: (args: string[]) => void | Promise<void>;\n}\n\nconst commands: Command[] = [\n {\n name: \"garden\",\n description: \"Manage git worktrees (gardens)\",\n subcommands: [\n {\n name: \"create\",\n description: \"Create a new worktree (garden)\",\n handler: gardensCreateHandler,\n },\n {\n name: \"list\",\n description: \"List all gardens\",\n handler: gardensListHandler,\n },\n {\n name: \"where\",\n description: \"Output the path of a specific garden\",\n handler: gardensWhereHandler,\n },\n {\n name: \"delete\",\n description: \"Delete a garden (use --force for dirty gardens)\",\n handler: gardensDeleteHandler,\n },\n ],\n },\n {\n name: \"exec\",\n description: \"Execute a command in a garden directory\",\n handler: execHandler,\n },\n {\n name: \"shell\",\n description: \"Open interactive shell in a garden directory\",\n handler: shellHandler,\n },\n];\n\nfunction printHelp(commands: Command[], prefix = \"\") {\n console.log(\"Usage: phantom <command> [options]\\n\");\n console.log(\"Commands:\");\n for (const cmd of commands) {\n console.log(` ${prefix}${cmd.name.padEnd(20)} ${cmd.description}`);\n if (cmd.subcommands) {\n for (const subcmd of cmd.subcommands) {\n console.log(` ${subcmd.name.padEnd(18)} ${subcmd.description}`);\n }\n }\n }\n}\n\nfunction findCommand(\n args: string[],\n commands: Command[],\n): { command: Command | null; remainingArgs: string[] } {\n if (args.length === 0) {\n return { command: null, remainingArgs: [] };\n }\n\n const [cmdName, ...rest] = args;\n const command = commands.find((cmd) => cmd.name === cmdName);\n\n if (!command) {\n return { command: null, remainingArgs: args };\n }\n\n if (command.subcommands && rest.length > 0) {\n const { command: subcommand, remainingArgs } = findCommand(\n rest,\n command.subcommands,\n );\n if (subcommand) {\n return { command: subcommand, remainingArgs };\n }\n }\n\n return { command, remainingArgs: rest };\n}\n\nconst args = argv.slice(2);\n\nif (args.length === 0 || args[0] === \"-h\" || args[0] === \"--help\") {\n printHelp(commands);\n exit(0);\n}\n\nconst { command, remainingArgs } = findCommand(args, commands);\n\nif (!command || !command.handler) {\n console.error(`Error: Unknown command '${args.join(\" \")}'\\n`);\n printHelp(commands);\n exit(1);\n}\n\ntry {\n await command.handler(remainingArgs);\n} catch (error) {\n console.error(\n \"Error:\",\n error instanceof Error ? error.message : String(error),\n );\n exit(1);\n}\n", "import { spawn } from \"node:child_process\";\nimport { exit } from \"node:process\";\nimport { whereGarden } from \"../gardens/commands/where.ts\";\n\nexport async function execInGarden(\n gardenName: string,\n command: string[],\n): Promise<{\n success: boolean;\n message?: string;\n exitCode?: number;\n}> {\n if (!gardenName) {\n return { success: false, message: \"Error: garden name required\" };\n }\n\n if (!command || command.length === 0) {\n return { success: false, message: \"Error: command required\" };\n }\n\n // Validate garden exists and get its path\n const gardenResult = await whereGarden(gardenName);\n if (!gardenResult.success) {\n return { success: false, message: gardenResult.message };\n }\n\n const gardenPath = gardenResult.path as string;\n const [cmd, ...args] = command;\n\n return new Promise((resolve) => {\n const childProcess = spawn(cmd, args, {\n cwd: gardenPath,\n stdio: \"inherit\",\n });\n\n childProcess.on(\"error\", (error) => {\n resolve({\n success: false,\n message: `Error executing command: ${error.message}`,\n });\n });\n\n childProcess.on(\"exit\", (code, signal) => {\n if (signal) {\n resolve({\n success: false,\n message: `Command terminated by signal: ${signal}`,\n exitCode: 128 + (signal === \"SIGTERM\" ? 15 : 1),\n });\n } else {\n const exitCode = code ?? 0;\n resolve({\n success: exitCode === 0,\n exitCode,\n });\n }\n });\n });\n}\n\nexport async function execHandler(args: string[]): Promise<void> {\n if (args.length < 2) {\n console.error(\"Usage: phantom exec <garden-name> <command> [args...]\");\n exit(1);\n }\n\n const gardenName = args[0];\n const command = args.slice(1);\n\n const result = await execInGarden(gardenName, command);\n\n if (!result.success) {\n if (result.message) {\n console.error(result.message);\n }\n exit(result.exitCode ?? 1);\n }\n\n // For successful commands, exit with the same code as the child process\n exit(result.exitCode ?? 0);\n}\n", "import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { exit } from \"node:process\";\nimport { getGitRoot } from \"../../git/libs/get-git-root.ts\";\n\nexport async function whereGarden(name: string): Promise<{\n success: boolean;\n message?: string;\n path?: string;\n}> {\n if (!name) {\n return { success: false, message: \"Error: garden name required\" };\n }\n\n try {\n const gitRoot = await getGitRoot();\n const gardensPath = join(gitRoot, \".git\", \"phantom\", \"gardens\");\n const gardenPath = join(gardensPath, name);\n\n // Check if garden exists\n try {\n await access(gardenPath);\n } catch {\n return {\n success: false,\n message: `Error: Garden '${name}' does not exist`,\n };\n }\n\n return {\n success: true,\n path: gardenPath,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error locating garden: ${errorMessage}`,\n };\n }\n}\n\nexport async function gardensWhereHandler(args: string[]): Promise<void> {\n const name = args[0];\n const result = await whereGarden(name);\n\n if (!result.success) {\n console.error(result.message);\n exit(1);\n }\n\n console.log(result.path);\n}\n", "import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\n\nexport async function getGitRoot(): Promise<string> {\n const { stdout } = await execAsync(\"git rev-parse --show-toplevel\");\n return stdout.trim();\n}\n", "import { spawn } from \"node:child_process\";\nimport { exit } from \"node:process\";\nimport { whereGarden } from \"../gardens/commands/where.ts\";\n\nexport async function shellInGarden(gardenName: string): Promise<{\n success: boolean;\n message?: string;\n exitCode?: number;\n}> {\n if (!gardenName) {\n return { success: false, message: \"Error: garden name required\" };\n }\n\n // Validate garden exists and get its path\n const gardenResult = await whereGarden(gardenName);\n if (!gardenResult.success) {\n return { success: false, message: gardenResult.message };\n }\n\n const gardenPath = gardenResult.path as string;\n // Use user's preferred shell or fallback to /bin/sh\n const shell = process.env.SHELL || \"/bin/sh\";\n\n return new Promise((resolve) => {\n const childProcess = spawn(shell, [], {\n cwd: gardenPath,\n stdio: \"inherit\",\n env: {\n ...process.env,\n // Add environment variable to indicate we're in a phantom garden\n PHANTOM_GARDEN: gardenName,\n PHANTOM_GARDEN_PATH: gardenPath,\n },\n });\n\n childProcess.on(\"error\", (error) => {\n resolve({\n success: false,\n message: `Error starting shell: ${error.message}`,\n });\n });\n\n childProcess.on(\"exit\", (code, signal) => {\n if (signal) {\n resolve({\n success: false,\n message: `Shell terminated by signal: ${signal}`,\n exitCode: 128 + (signal === \"SIGTERM\" ? 15 : 1),\n });\n } else {\n const exitCode = code ?? 0;\n resolve({\n success: exitCode === 0,\n exitCode,\n });\n }\n });\n });\n}\n\nexport async function shellHandler(args: string[]): Promise<void> {\n if (args.length < 1) {\n console.error(\"Usage: phantom shell <garden-name>\");\n exit(1);\n }\n\n const gardenName = args[0];\n\n // Get garden path for display\n const gardenResult = await whereGarden(gardenName);\n if (!gardenResult.success) {\n console.error(gardenResult.message);\n exit(1);\n }\n\n // Display entering message\n console.log(`Entering garden '${gardenName}' at ${gardenResult.path}`);\n console.log(\"Type 'exit' to return to your original directory\\n\");\n\n const result = await shellInGarden(gardenName);\n\n if (!result.success) {\n if (result.message) {\n console.error(result.message);\n }\n exit(result.exitCode ?? 1);\n }\n\n // Exit with the same code as the shell\n exit(result.exitCode ?? 0);\n}\n", "import { access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { exit } from \"node:process\";\nimport { addWorktree } from \"../../git/libs/add-worktree.ts\";\nimport { getGitRoot } from \"../../git/libs/get-git-root.ts\";\n\nexport async function createGarden(name: string): Promise<{\n success: boolean;\n message: string;\n path?: string;\n}> {\n if (!name) {\n return { success: false, message: \"Error: garden name required\" };\n }\n\n try {\n const gitRoot = await getGitRoot();\n const gardensPath = join(gitRoot, \".git\", \"phantom\", \"gardens\");\n const worktreePath = join(gardensPath, name);\n\n try {\n await access(gardensPath);\n } catch {\n await mkdir(gardensPath, { recursive: true });\n }\n\n try {\n await access(worktreePath);\n return {\n success: false,\n message: `Error: garden '${name}' already exists`,\n };\n } catch {\n // Path doesn't exist, which is what we want\n }\n\n await addWorktree({\n path: worktreePath,\n branch: `phantom/gardens/${name}`,\n commitish: \"HEAD\",\n });\n\n return {\n success: true,\n message: `Created garden '${name}' at ${worktreePath}`,\n path: worktreePath,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error creating garden: ${errorMessage}`,\n };\n }\n}\n\nexport async function gardensCreateHandler(args: string[]): Promise<void> {\n const name = args[0];\n const result = await createGarden(name);\n\n if (!result.success) {\n console.error(result.message);\n exit(1);\n }\n\n console.log(result.message);\n}\n", "import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\n\nexport interface AddWorktreeOptions {\n path: string;\n branch: string;\n commitish?: string;\n}\n\nexport async function addWorktree(options: AddWorktreeOptions): Promise<void> {\n const { path, branch, commitish = \"HEAD\" } = options;\n\n await execAsync(`git worktree add \"${path}\" -b \"${branch}\" ${commitish}`);\n}\n", "import { exec } from \"node:child_process\";\nimport { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { exit } from \"node:process\";\nimport { promisify } from \"node:util\";\nimport { getGitRoot } from \"../../git/libs/get-git-root.ts\";\n\nconst execAsync = promisify(exec);\n\nexport async function deleteGarden(\n name: string,\n options: { force?: boolean } = {},\n): Promise<{\n success: boolean;\n message: string;\n hasUncommittedChanges?: boolean;\n changedFiles?: number;\n}> {\n if (!name) {\n return { success: false, message: \"Error: garden name required\" };\n }\n\n const { force = false } = options;\n\n try {\n const gitRoot = await getGitRoot();\n const gardensPath = join(gitRoot, \".git\", \"phantom\", \"gardens\");\n const gardenPath = join(gardensPath, name);\n\n // Check if garden exists\n try {\n await access(gardenPath);\n } catch {\n return {\n success: false,\n message: `Error: Garden '${name}' does not exist`,\n };\n }\n\n // Check for uncommitted changes\n let hasUncommittedChanges = false;\n let changedFiles = 0;\n try {\n const { stdout } = await execAsync(\"git status --porcelain\", {\n cwd: gardenPath,\n });\n const changes = stdout.trim();\n if (changes) {\n hasUncommittedChanges = true;\n changedFiles = changes.split(\"\\n\").length;\n }\n } catch {\n // If git status fails, assume no changes\n hasUncommittedChanges = false;\n }\n\n // If garden has uncommitted changes and --force is not specified, refuse deletion\n if (hasUncommittedChanges && !force) {\n return {\n success: false,\n message: `Error: Garden '${name}' has uncommitted changes (${changedFiles} files). Use --force to delete anyway.`,\n hasUncommittedChanges: true,\n changedFiles,\n };\n }\n\n // Remove git worktree\n try {\n await execAsync(`git worktree remove \"${gardenPath}\"`, {\n cwd: gitRoot,\n });\n } catch (error) {\n // If worktree remove fails, try force removal\n try {\n await execAsync(`git worktree remove --force \"${gardenPath}\"`, {\n cwd: gitRoot,\n });\n } catch {\n return {\n success: false,\n message: `Error: Failed to remove worktree for garden '${name}'`,\n };\n }\n }\n\n // Delete associated branch\n const branchName = `phantom/gardens/${name}`;\n try {\n await execAsync(`git branch -D \"${branchName}\"`, {\n cwd: gitRoot,\n });\n } catch {\n // Branch might not exist or already deleted - this is not an error\n // We'll still report success for the worktree removal\n }\n\n let message = `Deleted garden '${name}' and its branch '${branchName}'`;\n if (hasUncommittedChanges) {\n message = `Warning: Garden '${name}' had uncommitted changes (${changedFiles} files)\\n${message}`;\n }\n\n return {\n success: true,\n message,\n hasUncommittedChanges,\n changedFiles: hasUncommittedChanges ? changedFiles : undefined,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error deleting garden: ${errorMessage}`,\n };\n }\n}\n\nexport async function gardensDeleteHandler(args: string[]): Promise<void> {\n // Parse arguments for --force flag\n const forceIndex = args.indexOf(\"--force\");\n const force = forceIndex !== -1;\n\n // Remove --force from args to get the garden name\n const filteredArgs = args.filter((arg) => arg !== \"--force\");\n const name = filteredArgs[0];\n\n const result = await deleteGarden(name, { force });\n\n if (!result.success) {\n console.error(result.message);\n exit(1);\n }\n\n console.log(result.message);\n}\n", "import { exec } from \"node:child_process\";\nimport { access, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { getGitRoot } from \"../../git/libs/get-git-root.ts\";\n\nconst execAsync = promisify(exec);\n\nexport interface GardenInfo {\n name: string;\n branch: string;\n status: \"clean\" | \"dirty\";\n changedFiles?: number;\n}\n\nexport async function listGardens(): Promise<{\n success: boolean;\n message?: string;\n gardens?: GardenInfo[];\n}> {\n try {\n const gitRoot = await getGitRoot();\n const gardensPath = join(gitRoot, \".git\", \"phantom\", \"gardens\");\n\n // Check if gardens directory exists\n try {\n await access(gardensPath);\n } catch {\n return {\n success: true,\n gardens: [],\n message: \"No gardens found (gardens directory doesn't exist)\",\n };\n }\n\n // Read gardens directory\n let gardenNames: string[];\n try {\n const entries = await readdir(gardensPath);\n // Filter entries to only include directories\n const validEntries = await Promise.all(\n entries.map(async (entry) => {\n try {\n const entryPath = join(gardensPath, entry);\n await access(entryPath);\n return entry;\n } catch {\n return null;\n }\n }),\n );\n gardenNames = validEntries.filter(\n (entry): entry is string => entry !== null,\n );\n } catch {\n return {\n success: true,\n gardens: [],\n message: \"No gardens found (unable to read gardens directory)\",\n };\n }\n\n if (gardenNames.length === 0) {\n return {\n success: true,\n gardens: [],\n message: \"No gardens found\",\n };\n }\n\n // Get detailed information for each garden\n const gardens: GardenInfo[] = await Promise.all(\n gardenNames.map(async (name) => {\n const gardenPath = join(gardensPath, name);\n\n // Get current branch\n let branch = \"unknown\";\n try {\n const { stdout } = await execAsync(\"git branch --show-current\", {\n cwd: gardenPath,\n });\n branch = stdout.trim() || \"detached HEAD\";\n } catch {\n branch = \"unknown\";\n }\n\n // Get working directory status\n let status: \"clean\" | \"dirty\" = \"clean\";\n let changedFiles: number | undefined;\n try {\n const { stdout } = await execAsync(\"git status --porcelain\", {\n cwd: gardenPath,\n });\n const changes = stdout.trim();\n if (changes) {\n status = \"dirty\";\n changedFiles = changes.split(\"\\n\").length;\n }\n } catch {\n // If git status fails, assume unknown status\n status = \"clean\";\n }\n\n return {\n name,\n branch,\n status,\n changedFiles,\n };\n }),\n );\n\n return {\n success: true,\n gardens,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error listing gardens: ${errorMessage}`,\n };\n }\n}\n\nexport async function gardensListHandler(): Promise<void> {\n const result = await listGardens();\n\n if (!result.success) {\n console.error(result.message);\n return;\n }\n\n if (!result.gardens || result.gardens.length === 0) {\n console.log(result.message || \"No gardens found\");\n return;\n }\n\n console.log(\"Gardens:\");\n for (const garden of result.gardens) {\n const statusText =\n garden.status === \"clean\"\n ? \"[clean]\"\n : `[dirty: ${garden.changedFiles} files]`;\n\n console.log(\n ` ${garden.name.padEnd(20)} (branch: ${garden.branch.padEnd(20)}) ${statusText}`,\n );\n }\n\n console.log(`\\nTotal: ${result.gardens.length} gardens`);\n}\n"],
5
- "mappings": "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",
6
- "names": ["exit", "exit", "args", "command", "args", "exit", "spawn", "exit", "spawn", "args", "exit", "access", "join", "exit", "exec", "promisify", "execAsync", "join", "access", "args", "exit", "exec", "access", "join", "exit", "promisify", "execAsync", "promisify", "exec", "join", "access", "args", "exit", "exec", "access", "join", "promisify", "execAsync", "promisify", "exec", "join", "access", "commands", "args", "command", "remainingArgs", "exit"]
3
+ "sources": ["../src/bin/phantom.ts", "../src/commands/create.ts", "../src/git/libs/add-worktree.ts", "../src/git/libs/get-git-root.ts", "../src/commands/shell.ts", "../src/commands/where.ts", "../src/commands/delete.ts", "../src/commands/exec.ts", "../src/commands/list.ts", "../package.json", "../src/commands/version.ts"],
4
+ "sourcesContent": ["#!/usr/bin/env node\n\nimport { argv, exit } from \"node:process\";\nimport { createHandler } from \"../commands/create.ts\";\nimport { deleteHandler } from \"../commands/delete.ts\";\nimport { execHandler } from \"../commands/exec.ts\";\nimport { listHandler } from \"../commands/list.ts\";\nimport { shellHandler } from \"../commands/shell.ts\";\nimport { versionHandler } from \"../commands/version.ts\";\nimport { whereHandler } from \"../commands/where.ts\";\n\ninterface Command {\n name: string;\n description: string;\n subcommands?: Command[];\n handler?: (args: string[]) => void | Promise<void>;\n}\n\nconst commands: Command[] = [\n {\n name: \"create\",\n description: \"Create a new worktree [--shell to open shell]\",\n handler: createHandler,\n },\n {\n name: \"list\",\n description: \"List all worktrees\",\n handler: listHandler,\n },\n {\n name: \"where\",\n description: \"Output the path of a specific worktree\",\n handler: whereHandler,\n },\n {\n name: \"delete\",\n description: \"Delete a worktree (use --force for uncommitted changes)\",\n handler: deleteHandler,\n },\n {\n name: \"exec\",\n description: \"Execute a command in a worktree directory\",\n handler: execHandler,\n },\n {\n name: \"shell\",\n description: \"Open interactive shell in a worktree directory\",\n handler: shellHandler,\n },\n {\n name: \"version\",\n description: \"Display phantom version\",\n handler: versionHandler,\n },\n];\n\nfunction printHelp(commands: Command[]) {\n console.log(\"Usage: phantom <command> [options]\\n\");\n console.log(\"Commands:\");\n for (const cmd of commands) {\n console.log(` ${cmd.name.padEnd(12)} ${cmd.description}`);\n }\n}\n\nfunction findCommand(\n args: string[],\n commands: Command[],\n): { command: Command | null; remainingArgs: string[] } {\n if (args.length === 0) {\n return { command: null, remainingArgs: [] };\n }\n\n const [cmdName, ...rest] = args;\n const command = commands.find((cmd) => cmd.name === cmdName);\n\n if (!command) {\n return { command: null, remainingArgs: args };\n }\n\n if (command.subcommands && rest.length > 0) {\n const { command: subcommand, remainingArgs } = findCommand(\n rest,\n command.subcommands,\n );\n if (subcommand) {\n return { command: subcommand, remainingArgs };\n }\n }\n\n return { command, remainingArgs: rest };\n}\n\nconst args = argv.slice(2);\n\nif (args.length === 0 || args[0] === \"-h\" || args[0] === \"--help\") {\n printHelp(commands);\n exit(0);\n}\n\nif (args[0] === \"--version\" || args[0] === \"-v\") {\n versionHandler();\n exit(0);\n}\n\nconst { command, remainingArgs } = findCommand(args, commands);\n\nif (!command || !command.handler) {\n console.error(`Error: Unknown command '${args.join(\" \")}'\\n`);\n printHelp(commands);\n exit(1);\n}\n\ntry {\n await command.handler(remainingArgs);\n} catch (error) {\n console.error(\n \"Error:\",\n error instanceof Error ? error.message : String(error),\n );\n exit(1);\n}\n", "import { access, mkdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { exit } from \"node:process\";\nimport { addWorktree } from \"../git/libs/add-worktree.ts\";\nimport { getGitRoot } from \"../git/libs/get-git-root.ts\";\nimport { shellInWorktree } from \"./shell.ts\";\n\nexport async function createWorktree(name: string): Promise<{\n success: boolean;\n message: string;\n path?: string;\n}> {\n if (!name) {\n return { success: false, message: \"Error: worktree name required\" };\n }\n\n try {\n const gitRoot = await getGitRoot();\n const worktreesPath = join(gitRoot, \".git\", \"phantom\", \"worktrees\");\n const worktreePath = join(worktreesPath, name);\n\n try {\n await access(worktreesPath);\n } catch {\n await mkdir(worktreesPath, { recursive: true });\n }\n\n try {\n await access(worktreePath);\n return {\n success: false,\n message: `Error: worktree '${name}' already exists`,\n };\n } catch {\n // Path doesn't exist, which is what we want\n }\n\n await addWorktree({\n path: worktreePath,\n branch: name,\n commitish: \"HEAD\",\n });\n\n return {\n success: true,\n message: `Created worktree '${name}' at ${worktreePath}`,\n path: worktreePath,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error creating worktree: ${errorMessage}`,\n };\n }\n}\n\nexport async function createHandler(args: string[]): Promise<void> {\n const name = args[0];\n const openShell = args.includes(\"--shell\");\n\n const result = await createWorktree(name);\n\n if (!result.success) {\n console.error(result.message);\n exit(1);\n }\n\n console.log(result.message);\n\n if (openShell && result.path) {\n console.log(`\\nEntering worktree '${name}' at ${result.path}`);\n console.log(\"Type 'exit' to return to your original directory\\n\");\n\n const shellResult = await shellInWorktree(name);\n\n if (!shellResult.success) {\n if (shellResult.message) {\n console.error(shellResult.message);\n }\n exit(shellResult.exitCode ?? 1);\n }\n\n exit(shellResult.exitCode ?? 0);\n }\n}\n", "import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\n\nexport interface AddWorktreeOptions {\n path: string;\n branch: string;\n commitish?: string;\n}\n\nexport async function addWorktree(options: AddWorktreeOptions): Promise<void> {\n const { path, branch, commitish = \"HEAD\" } = options;\n\n await execAsync(`git worktree add \"${path}\" -b \"${branch}\" ${commitish}`);\n}\n", "import { exec } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nconst execAsync = promisify(exec);\n\nexport async function getGitRoot(): Promise<string> {\n const { stdout } = await execAsync(\"git rev-parse --show-toplevel\");\n return stdout.trim();\n}\n", "import { spawn } from \"node:child_process\";\nimport { exit } from \"node:process\";\nimport { whereWorktree } from \"./where.ts\";\n\nexport async function shellInWorktree(worktreeName: string): Promise<{\n success: boolean;\n message?: string;\n exitCode?: number;\n}> {\n if (!worktreeName) {\n return { success: false, message: \"Error: worktree name required\" };\n }\n\n // Validate worktree exists and get its path\n const worktreeResult = await whereWorktree(worktreeName);\n if (!worktreeResult.success) {\n return { success: false, message: worktreeResult.message };\n }\n\n const worktreePath = worktreeResult.path as string;\n // Use user's preferred shell or fallback to /bin/sh\n const shell = process.env.SHELL || \"/bin/sh\";\n\n return new Promise((resolve) => {\n const childProcess = spawn(shell, [], {\n cwd: worktreePath,\n stdio: \"inherit\",\n env: {\n ...process.env,\n // Add environment variable to indicate we're in a worktree\n WORKTREE_NAME: worktreeName,\n WORKTREE_PATH: worktreePath,\n },\n });\n\n childProcess.on(\"error\", (error) => {\n resolve({\n success: false,\n message: `Error starting shell: ${error.message}`,\n });\n });\n\n childProcess.on(\"exit\", (code, signal) => {\n if (signal) {\n resolve({\n success: false,\n message: `Shell terminated by signal: ${signal}`,\n exitCode: 128 + (signal === \"SIGTERM\" ? 15 : 1),\n });\n } else {\n const exitCode = code ?? 0;\n resolve({\n success: exitCode === 0,\n exitCode,\n });\n }\n });\n });\n}\n\nexport async function shellHandler(args: string[]): Promise<void> {\n if (args.length < 1) {\n console.error(\"Usage: phantom shell <worktree-name>\");\n exit(1);\n }\n\n const worktreeName = args[0];\n\n // Get worktree path for display\n const worktreeResult = await whereWorktree(worktreeName);\n if (!worktreeResult.success) {\n console.error(worktreeResult.message);\n exit(1);\n }\n\n // Display entering message\n console.log(`Entering worktree '${worktreeName}' at ${worktreeResult.path}`);\n console.log(\"Type 'exit' to return to your original directory\\n\");\n\n const result = await shellInWorktree(worktreeName);\n\n if (!result.success) {\n if (result.message) {\n console.error(result.message);\n }\n exit(result.exitCode ?? 1);\n }\n\n // Exit with the same code as the shell\n exit(result.exitCode ?? 0);\n}\n", "import { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { exit } from \"node:process\";\nimport { getGitRoot } from \"../git/libs/get-git-root.ts\";\n\nexport async function whereWorktree(name: string): Promise<{\n success: boolean;\n message?: string;\n path?: string;\n}> {\n if (!name) {\n return { success: false, message: \"Error: worktree name required\" };\n }\n\n try {\n const gitRoot = await getGitRoot();\n const worktreesPath = join(gitRoot, \".git\", \"phantom\", \"worktrees\");\n const worktreePath = join(worktreesPath, name);\n\n // Check if worktree exists\n try {\n await access(worktreePath);\n } catch {\n return {\n success: false,\n message: `Error: Worktree '${name}' does not exist`,\n };\n }\n\n return {\n success: true,\n path: worktreePath,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error locating worktree: ${errorMessage}`,\n };\n }\n}\n\nexport async function whereHandler(args: string[]): Promise<void> {\n const name = args[0];\n const result = await whereWorktree(name);\n\n if (!result.success) {\n console.error(result.message);\n exit(1);\n }\n\n console.log(result.path);\n}\n", "import { exec } from \"node:child_process\";\nimport { access } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { exit } from \"node:process\";\nimport { promisify } from \"node:util\";\nimport { getGitRoot } from \"../git/libs/get-git-root.ts\";\n\nconst execAsync = promisify(exec);\n\nexport async function deleteWorktree(\n name: string,\n options: { force?: boolean } = {},\n): Promise<{\n success: boolean;\n message: string;\n hasUncommittedChanges?: boolean;\n changedFiles?: number;\n}> {\n if (!name) {\n return { success: false, message: \"Error: worktree name required\" };\n }\n\n const { force = false } = options;\n\n try {\n const gitRoot = await getGitRoot();\n const worktreesPath = join(gitRoot, \".git\", \"phantom\", \"worktrees\");\n const worktreePath = join(worktreesPath, name);\n\n // Check if worktree exists\n try {\n await access(worktreePath);\n } catch {\n return {\n success: false,\n message: `Error: Worktree '${name}' does not exist`,\n };\n }\n\n // Check for uncommitted changes\n let hasUncommittedChanges = false;\n let changedFiles = 0;\n try {\n const { stdout } = await execAsync(\"git status --porcelain\", {\n cwd: worktreePath,\n });\n const changes = stdout.trim();\n if (changes) {\n hasUncommittedChanges = true;\n changedFiles = changes.split(\"\\n\").length;\n }\n } catch {\n // If git status fails, assume no changes\n hasUncommittedChanges = false;\n }\n\n // If worktree has uncommitted changes and --force is not specified, refuse deletion\n if (hasUncommittedChanges && !force) {\n return {\n success: false,\n message: `Error: Worktree '${name}' has uncommitted changes (${changedFiles} files). Use --force to delete anyway.`,\n hasUncommittedChanges: true,\n changedFiles,\n };\n }\n\n // Remove git worktree\n try {\n await execAsync(`git worktree remove \"${worktreePath}\"`, {\n cwd: gitRoot,\n });\n } catch (error) {\n // If worktree remove fails, try force removal\n try {\n await execAsync(`git worktree remove --force \"${worktreePath}\"`, {\n cwd: gitRoot,\n });\n } catch {\n return {\n success: false,\n message: `Error: Failed to remove worktree '${name}'`,\n };\n }\n }\n\n // Delete associated branch\n const branchName = `phantom/worktrees/${name}`;\n try {\n await execAsync(`git branch -D \"${branchName}\"`, {\n cwd: gitRoot,\n });\n } catch {\n // Branch might not exist or already deleted - this is not an error\n // We'll still report success for the worktree removal\n }\n\n let message = `Deleted worktree '${name}' and its branch '${branchName}'`;\n if (hasUncommittedChanges) {\n message = `Warning: Worktree '${name}' had uncommitted changes (${changedFiles} files)\\n${message}`;\n }\n\n return {\n success: true,\n message,\n hasUncommittedChanges,\n changedFiles: hasUncommittedChanges ? changedFiles : undefined,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error deleting worktree: ${errorMessage}`,\n };\n }\n}\n\nexport async function deleteHandler(args: string[]): Promise<void> {\n // Parse arguments for --force flag\n const forceIndex = args.indexOf(\"--force\");\n const force = forceIndex !== -1;\n\n // Remove --force from args to get the worktree name\n const filteredArgs = args.filter((arg) => arg !== \"--force\");\n const name = filteredArgs[0];\n\n const result = await deleteWorktree(name, { force });\n\n if (!result.success) {\n console.error(result.message);\n exit(1);\n }\n\n console.log(result.message);\n}\n", "import { spawn } from \"node:child_process\";\nimport { exit } from \"node:process\";\nimport { whereWorktree } from \"./where.ts\";\n\nexport async function execInWorktree(\n worktreeName: string,\n command: string[],\n): Promise<{\n success: boolean;\n message?: string;\n exitCode?: number;\n}> {\n if (!worktreeName) {\n return { success: false, message: \"Error: worktree name required\" };\n }\n\n if (!command || command.length === 0) {\n return { success: false, message: \"Error: command required\" };\n }\n\n // Validate worktree exists and get its path\n const worktreeResult = await whereWorktree(worktreeName);\n if (!worktreeResult.success) {\n return { success: false, message: worktreeResult.message };\n }\n\n const worktreePath = worktreeResult.path as string;\n const [cmd, ...args] = command;\n\n return new Promise((resolve) => {\n const childProcess = spawn(cmd, args, {\n cwd: worktreePath,\n stdio: \"inherit\",\n });\n\n childProcess.on(\"error\", (error) => {\n resolve({\n success: false,\n message: `Error executing command: ${error.message}`,\n });\n });\n\n childProcess.on(\"exit\", (code, signal) => {\n if (signal) {\n resolve({\n success: false,\n message: `Command terminated by signal: ${signal}`,\n exitCode: 128 + (signal === \"SIGTERM\" ? 15 : 1),\n });\n } else {\n const exitCode = code ?? 0;\n resolve({\n success: exitCode === 0,\n exitCode,\n });\n }\n });\n });\n}\n\nexport async function execHandler(args: string[]): Promise<void> {\n if (args.length < 2) {\n console.error(\"Usage: phantom exec <worktree-name> <command> [args...]\");\n exit(1);\n }\n\n const worktreeName = args[0];\n const command = args.slice(1);\n\n const result = await execInWorktree(worktreeName, command);\n\n if (!result.success) {\n if (result.message) {\n console.error(result.message);\n }\n exit(result.exitCode ?? 1);\n }\n\n // For successful commands, exit with the same code as the child process\n exit(result.exitCode ?? 0);\n}\n", "import { exec } from \"node:child_process\";\nimport { access, readdir } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { promisify } from \"node:util\";\nimport { getGitRoot } from \"../git/libs/get-git-root.ts\";\n\nconst execAsync = promisify(exec);\n\nexport interface WorktreeInfo {\n name: string;\n branch: string;\n status: \"clean\" | \"dirty\";\n changedFiles?: number;\n}\n\nexport async function listWorktrees(): Promise<{\n success: boolean;\n message?: string;\n worktrees?: WorktreeInfo[];\n}> {\n try {\n const gitRoot = await getGitRoot();\n const worktreesPath = join(gitRoot, \".git\", \"phantom\", \"worktrees\");\n\n // Check if worktrees directory exists\n try {\n await access(worktreesPath);\n } catch {\n return {\n success: true,\n worktrees: [],\n message: \"No worktrees found (worktrees directory doesn't exist)\",\n };\n }\n\n // Read worktrees directory\n let worktreeNames: string[];\n try {\n const entries = await readdir(worktreesPath);\n // Filter entries to only include directories\n const validEntries = await Promise.all(\n entries.map(async (entry) => {\n try {\n const entryPath = join(worktreesPath, entry);\n await access(entryPath);\n return entry;\n } catch {\n return null;\n }\n }),\n );\n worktreeNames = validEntries.filter(\n (entry): entry is string => entry !== null,\n );\n } catch {\n return {\n success: true,\n worktrees: [],\n message: \"No worktrees found (unable to read worktrees directory)\",\n };\n }\n\n if (worktreeNames.length === 0) {\n return {\n success: true,\n worktrees: [],\n message: \"No worktrees found\",\n };\n }\n\n // Get detailed information for each worktree\n const worktrees: WorktreeInfo[] = await Promise.all(\n worktreeNames.map(async (name) => {\n const worktreePath = join(worktreesPath, name);\n\n // Get current branch\n let branch = \"unknown\";\n try {\n const { stdout } = await execAsync(\"git branch --show-current\", {\n cwd: worktreePath,\n });\n branch = stdout.trim() || \"detached HEAD\";\n } catch {\n branch = \"unknown\";\n }\n\n // Get working directory status\n let status: \"clean\" | \"dirty\" = \"clean\";\n let changedFiles: number | undefined;\n try {\n const { stdout } = await execAsync(\"git status --porcelain\", {\n cwd: worktreePath,\n });\n const changes = stdout.trim();\n if (changes) {\n status = \"dirty\";\n changedFiles = changes.split(\"\\n\").length;\n }\n } catch {\n // If git status fails, assume unknown status\n status = \"clean\";\n }\n\n return {\n name,\n branch,\n status,\n changedFiles,\n };\n }),\n );\n\n return {\n success: true,\n worktrees,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n message: `Error listing worktrees: ${errorMessage}`,\n };\n }\n}\n\nexport async function listHandler(): Promise<void> {\n const result = await listWorktrees();\n\n if (!result.success) {\n console.error(result.message);\n return;\n }\n\n if (!result.worktrees || result.worktrees.length === 0) {\n console.log(result.message || \"No worktrees found\");\n return;\n }\n\n console.log(\"Worktrees:\");\n for (const worktree of result.worktrees) {\n const statusText =\n worktree.status === \"clean\"\n ? \"[clean]\"\n : `[dirty: ${worktree.changedFiles} files]`;\n\n console.log(\n ` ${worktree.name.padEnd(20)} (branch: ${worktree.branch.padEnd(20)}) ${statusText}`,\n );\n }\n\n console.log(`\\nTotal: ${result.worktrees.length} worktrees`);\n}\n", "{\n \"name\": \"@aku11i/phantom\",\n \"packageManager\": \"pnpm@10.8.1\",\n \"version\": \"0.3.0\",\n \"description\": \"A powerful CLI tool for managing Git worktrees for parallel development\",\n \"keywords\": [\n \"git\",\n \"worktree\",\n \"cli\",\n \"phantom\",\n \"workspace\",\n \"development\",\n \"parallel\"\n ],\n \"homepage\": \"https://github.com/aku11i/phantom#readme\",\n \"bugs\": {\n \"url\": \"https://github.com/aku11i/phantom/issues\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/aku11i/phantom.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"aku11i\",\n \"type\": \"module\",\n \"bin\": {\n \"phantom\": \"./dist/phantom.js\"\n },\n \"scripts\": {\n \"start\": \"node ./src/bin/phantom.ts\",\n \"phantom\": \"node ./src/bin/phantom.ts\",\n \"build\": \"node build.ts\",\n \"type-check\": \"tsc --noEmit\",\n \"test\": \"node --test --experimental-strip-types --experimental-test-module-mocks src/**/*.test.ts\",\n \"lint\": \"biome check .\",\n \"fix\": \"biome check --write .\",\n \"ready\": \"pnpm fix && pnpm type-check && pnpm test\",\n \"ready:check\": \"pnpm lint && pnpm type-check && pnpm test\",\n \"prepublishOnly\": \"pnpm ready:check && pnpm build\"\n },\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"files\": [\n \"dist/\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"devDependencies\": {\n \"@biomejs/biome\": \"^1.9.4\",\n \"@types/node\": \"^22.15.29\",\n \"esbuild\": \"^0.25.5\",\n \"typescript\": \"^5.8.3\"\n }\n}\n", "import packageJson from \"../../package.json\" with { type: \"json\" };\n\nexport function getVersion(): string {\n return packageJson.version;\n}\n\nexport function versionHandler(): void {\n const version = getVersion();\n console.log(`Phantom v${version}`);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["exit", "access", "join", "exit", "exec", "promisify", "execAsync", "exit", "args", "args", "exit", "join", "access", "args", "exit", "exec", "access", "join", "exit", "promisify", "execAsync", "promisify", "exec", "join", "access", "args", "exit", "spawn", "exit", "command", "args", "spawn", "exit", "exec", "access", "join", "promisify", "execAsync", "promisify", "exec", "join", "access", "commands", "args", "command", "remainingArgs", "exit"]
7
7
  }
package/package.json CHANGED
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@aku11i/phantom",
3
- "version": "0.1.2",
4
- "description": "A CLI tool for managing Git worktrees (gardens) with enhanced functionality",
3
+ "version": "0.3.0",
4
+ "description": "A powerful CLI tool for managing Git worktrees for parallel development",
5
5
  "keywords": [
6
6
  "git",
7
7
  "worktree",
8
8
  "cli",
9
9
  "phantom",
10
- "gardens",
11
10
  "workspace",
12
- "development"
11
+ "development",
12
+ "parallel"
13
13
  ],
14
14
  "homepage": "https://github.com/aku11i/phantom#readme",
15
15
  "bugs": {
@@ -23,11 +23,10 @@
23
23
  "author": "aku11i",
24
24
  "type": "module",
25
25
  "bin": {
26
- "phantom": "./dist/phantom.js",
27
- "garden": "./dist/garden.js"
26
+ "phantom": "./dist/phantom.js"
28
27
  },
29
28
  "engines": {
30
- "node": ">=20.0.0"
29
+ "node": ">=22.0.0"
31
30
  },
32
31
  "files": [
33
32
  "dist/",
@@ -43,10 +42,9 @@
43
42
  "scripts": {
44
43
  "start": "node ./src/bin/phantom.ts",
45
44
  "phantom": "node ./src/bin/phantom.ts",
46
- "garden": "node ./src/bin/garden.ts",
47
45
  "build": "node build.ts",
48
46
  "type-check": "tsc --noEmit",
49
- "test": "node --test --experimental-test-module-mocks src/**/*.test.ts",
47
+ "test": "node --test --experimental-strip-types --experimental-test-module-mocks src/**/*.test.ts",
50
48
  "lint": "biome check .",
51
49
  "fix": "biome check --write .",
52
50
  "ready": "pnpm fix && pnpm type-check && pnpm test",
package/dist/garden.js DELETED
@@ -1,394 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- // src/bin/garden.ts
4
- import { argv, exit as exit4 } from "node:process";
5
-
6
- // src/gardens/commands/create.ts
7
- import { access, mkdir } from "node:fs/promises";
8
- import { join } from "node:path";
9
- import { exit } from "node:process";
10
-
11
- // src/git/libs/add-worktree.ts
12
- import { exec } from "node:child_process";
13
- import { promisify } from "node:util";
14
- var execAsync = promisify(exec);
15
- async function addWorktree(options) {
16
- const { path, branch, commitish = "HEAD" } = options;
17
- await execAsync(`git worktree add "${path}" -b "${branch}" ${commitish}`);
18
- }
19
-
20
- // src/git/libs/get-git-root.ts
21
- import { exec as exec2 } from "node:child_process";
22
- import { promisify as promisify2 } from "node:util";
23
- var execAsync2 = promisify2(exec2);
24
- async function getGitRoot() {
25
- const { stdout } = await execAsync2("git rev-parse --show-toplevel");
26
- return stdout.trim();
27
- }
28
-
29
- // src/gardens/commands/create.ts
30
- async function createGarden(name) {
31
- if (!name) {
32
- return { success: false, message: "Error: garden name required" };
33
- }
34
- try {
35
- const gitRoot = await getGitRoot();
36
- const gardensPath = join(gitRoot, ".git", "phantom", "gardens");
37
- const worktreePath = join(gardensPath, name);
38
- try {
39
- await access(gardensPath);
40
- } catch {
41
- await mkdir(gardensPath, { recursive: true });
42
- }
43
- try {
44
- await access(worktreePath);
45
- return {
46
- success: false,
47
- message: `Error: garden '${name}' already exists`
48
- };
49
- } catch {
50
- }
51
- await addWorktree({
52
- path: worktreePath,
53
- branch: `phantom/gardens/${name}`,
54
- commitish: "HEAD"
55
- });
56
- return {
57
- success: true,
58
- message: `Created garden '${name}' at ${worktreePath}`,
59
- path: worktreePath
60
- };
61
- } catch (error) {
62
- const errorMessage = error instanceof Error ? error.message : String(error);
63
- return {
64
- success: false,
65
- message: `Error creating garden: ${errorMessage}`
66
- };
67
- }
68
- }
69
- async function gardensCreateHandler(args2) {
70
- const name = args2[0];
71
- const result = await createGarden(name);
72
- if (!result.success) {
73
- console.error(result.message);
74
- exit(1);
75
- }
76
- console.log(result.message);
77
- }
78
-
79
- // src/gardens/commands/delete.ts
80
- import { exec as exec3 } from "node:child_process";
81
- import { access as access2 } from "node:fs/promises";
82
- import { join as join2 } from "node:path";
83
- import { exit as exit2 } from "node:process";
84
- import { promisify as promisify3 } from "node:util";
85
- var execAsync3 = promisify3(exec3);
86
- async function deleteGarden(name, options = {}) {
87
- if (!name) {
88
- return { success: false, message: "Error: garden name required" };
89
- }
90
- const { force = false } = options;
91
- try {
92
- const gitRoot = await getGitRoot();
93
- const gardensPath = join2(gitRoot, ".git", "phantom", "gardens");
94
- const gardenPath = join2(gardensPath, name);
95
- try {
96
- await access2(gardenPath);
97
- } catch {
98
- return {
99
- success: false,
100
- message: `Error: Garden '${name}' does not exist`
101
- };
102
- }
103
- let hasUncommittedChanges = false;
104
- let changedFiles = 0;
105
- try {
106
- const { stdout } = await execAsync3("git status --porcelain", {
107
- cwd: gardenPath
108
- });
109
- const changes = stdout.trim();
110
- if (changes) {
111
- hasUncommittedChanges = true;
112
- changedFiles = changes.split("\n").length;
113
- }
114
- } catch {
115
- hasUncommittedChanges = false;
116
- }
117
- if (hasUncommittedChanges && !force) {
118
- return {
119
- success: false,
120
- message: `Error: Garden '${name}' has uncommitted changes (${changedFiles} files). Use --force to delete anyway.`,
121
- hasUncommittedChanges: true,
122
- changedFiles
123
- };
124
- }
125
- try {
126
- await execAsync3(`git worktree remove "${gardenPath}"`, {
127
- cwd: gitRoot
128
- });
129
- } catch (error) {
130
- try {
131
- await execAsync3(`git worktree remove --force "${gardenPath}"`, {
132
- cwd: gitRoot
133
- });
134
- } catch {
135
- return {
136
- success: false,
137
- message: `Error: Failed to remove worktree for garden '${name}'`
138
- };
139
- }
140
- }
141
- const branchName = `phantom/gardens/${name}`;
142
- try {
143
- await execAsync3(`git branch -D "${branchName}"`, {
144
- cwd: gitRoot
145
- });
146
- } catch {
147
- }
148
- let message = `Deleted garden '${name}' and its branch '${branchName}'`;
149
- if (hasUncommittedChanges) {
150
- message = `Warning: Garden '${name}' had uncommitted changes (${changedFiles} files)
151
- ${message}`;
152
- }
153
- return {
154
- success: true,
155
- message,
156
- hasUncommittedChanges,
157
- changedFiles: hasUncommittedChanges ? changedFiles : void 0
158
- };
159
- } catch (error) {
160
- const errorMessage = error instanceof Error ? error.message : String(error);
161
- return {
162
- success: false,
163
- message: `Error deleting garden: ${errorMessage}`
164
- };
165
- }
166
- }
167
- async function gardensDeleteHandler(args2) {
168
- const forceIndex = args2.indexOf("--force");
169
- const force = forceIndex !== -1;
170
- const filteredArgs = args2.filter((arg) => arg !== "--force");
171
- const name = filteredArgs[0];
172
- const result = await deleteGarden(name, { force });
173
- if (!result.success) {
174
- console.error(result.message);
175
- exit2(1);
176
- }
177
- console.log(result.message);
178
- }
179
-
180
- // src/gardens/commands/list.ts
181
- import { exec as exec4 } from "node:child_process";
182
- import { access as access3, readdir } from "node:fs/promises";
183
- import { join as join3 } from "node:path";
184
- import { promisify as promisify4 } from "node:util";
185
- var execAsync4 = promisify4(exec4);
186
- async function listGardens() {
187
- try {
188
- const gitRoot = await getGitRoot();
189
- const gardensPath = join3(gitRoot, ".git", "phantom", "gardens");
190
- try {
191
- await access3(gardensPath);
192
- } catch {
193
- return {
194
- success: true,
195
- gardens: [],
196
- message: "No gardens found (gardens directory doesn't exist)"
197
- };
198
- }
199
- let gardenNames;
200
- try {
201
- const entries = await readdir(gardensPath);
202
- const validEntries = await Promise.all(
203
- entries.map(async (entry) => {
204
- try {
205
- const entryPath = join3(gardensPath, entry);
206
- await access3(entryPath);
207
- return entry;
208
- } catch {
209
- return null;
210
- }
211
- })
212
- );
213
- gardenNames = validEntries.filter(
214
- (entry) => entry !== null
215
- );
216
- } catch {
217
- return {
218
- success: true,
219
- gardens: [],
220
- message: "No gardens found (unable to read gardens directory)"
221
- };
222
- }
223
- if (gardenNames.length === 0) {
224
- return {
225
- success: true,
226
- gardens: [],
227
- message: "No gardens found"
228
- };
229
- }
230
- const gardens = await Promise.all(
231
- gardenNames.map(async (name) => {
232
- const gardenPath = join3(gardensPath, name);
233
- let branch = "unknown";
234
- try {
235
- const { stdout } = await execAsync4("git branch --show-current", {
236
- cwd: gardenPath
237
- });
238
- branch = stdout.trim() || "detached HEAD";
239
- } catch {
240
- branch = "unknown";
241
- }
242
- let status = "clean";
243
- let changedFiles;
244
- try {
245
- const { stdout } = await execAsync4("git status --porcelain", {
246
- cwd: gardenPath
247
- });
248
- const changes = stdout.trim();
249
- if (changes) {
250
- status = "dirty";
251
- changedFiles = changes.split("\n").length;
252
- }
253
- } catch {
254
- status = "clean";
255
- }
256
- return {
257
- name,
258
- branch,
259
- status,
260
- changedFiles
261
- };
262
- })
263
- );
264
- return {
265
- success: true,
266
- gardens
267
- };
268
- } catch (error) {
269
- const errorMessage = error instanceof Error ? error.message : String(error);
270
- return {
271
- success: false,
272
- message: `Error listing gardens: ${errorMessage}`
273
- };
274
- }
275
- }
276
- async function gardensListHandler() {
277
- const result = await listGardens();
278
- if (!result.success) {
279
- console.error(result.message);
280
- return;
281
- }
282
- if (!result.gardens || result.gardens.length === 0) {
283
- console.log(result.message || "No gardens found");
284
- return;
285
- }
286
- console.log("Gardens:");
287
- for (const garden of result.gardens) {
288
- const statusText = garden.status === "clean" ? "[clean]" : `[dirty: ${garden.changedFiles} files]`;
289
- console.log(
290
- ` ${garden.name.padEnd(20)} (branch: ${garden.branch.padEnd(20)}) ${statusText}`
291
- );
292
- }
293
- console.log(`
294
- Total: ${result.gardens.length} gardens`);
295
- }
296
-
297
- // src/gardens/commands/where.ts
298
- import { access as access4 } from "node:fs/promises";
299
- import { join as join4 } from "node:path";
300
- import { exit as exit3 } from "node:process";
301
- async function whereGarden(name) {
302
- if (!name) {
303
- return { success: false, message: "Error: garden name required" };
304
- }
305
- try {
306
- const gitRoot = await getGitRoot();
307
- const gardensPath = join4(gitRoot, ".git", "phantom", "gardens");
308
- const gardenPath = join4(gardensPath, name);
309
- try {
310
- await access4(gardenPath);
311
- } catch {
312
- return {
313
- success: false,
314
- message: `Error: Garden '${name}' does not exist`
315
- };
316
- }
317
- return {
318
- success: true,
319
- path: gardenPath
320
- };
321
- } catch (error) {
322
- const errorMessage = error instanceof Error ? error.message : String(error);
323
- return {
324
- success: false,
325
- message: `Error locating garden: ${errorMessage}`
326
- };
327
- }
328
- }
329
- async function gardensWhereHandler(args2) {
330
- const name = args2[0];
331
- const result = await whereGarden(name);
332
- if (!result.success) {
333
- console.error(result.message);
334
- exit3(1);
335
- }
336
- console.log(result.path);
337
- }
338
-
339
- // src/bin/garden.ts
340
- var commands = [
341
- {
342
- name: "create",
343
- description: "Create a new worktree (garden)",
344
- handler: gardensCreateHandler
345
- },
346
- {
347
- name: "list",
348
- description: "List all gardens",
349
- handler: gardensListHandler
350
- },
351
- {
352
- name: "where",
353
- description: "Output the path of a specific garden",
354
- handler: gardensWhereHandler
355
- },
356
- {
357
- name: "delete",
358
- description: "Delete a garden (use --force for dirty gardens)",
359
- handler: gardensDeleteHandler
360
- }
361
- ];
362
- function printHelp() {
363
- console.log("Usage: garden <command> [options]\n");
364
- console.log("Commands:");
365
- for (const cmd of commands) {
366
- console.log(` ${cmd.name.padEnd(20)} ${cmd.description}`);
367
- }
368
- console.log("\nThis is an alias for 'phantom garden' commands.");
369
- }
370
- function findCommand(cmdName, commands2) {
371
- return commands2.find((cmd) => cmd.name === cmdName) || null;
372
- }
373
- var args = argv.slice(2);
374
- if (args.length === 0 || args[0] === "-h" || args[0] === "--help") {
375
- printHelp();
376
- exit4(0);
377
- }
378
- var command = findCommand(args[0], commands);
379
- if (!command || !command.handler) {
380
- console.error(`Error: Unknown command '${args[0]}'
381
- `);
382
- printHelp();
383
- exit4(1);
384
- }
385
- try {
386
- await command.handler(args.slice(1));
387
- } catch (error) {
388
- console.error(
389
- "Error:",
390
- error instanceof Error ? error.message : String(error)
391
- );
392
- exit4(1);
393
- }
394
- //# sourceMappingURL=garden.js.map