@iloom/cli 0.5.0 → 0.5.2
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.
- package/dist/{BranchNamingService-GCCWB3LK.js → BranchNamingService-B5PVRR7F.js} +4 -4
- package/dist/ClaudeContextManager-PQ46VILL.js +14 -0
- package/dist/ClaudeService-6OMO552H.js +13 -0
- package/dist/GitHubService-S2OGUTDR.js +12 -0
- package/dist/{LoomLauncher-4UG2E4CD.js → LoomLauncher-ZHDTPKED.js} +15 -79
- package/dist/LoomLauncher-ZHDTPKED.js.map +1 -0
- package/dist/MetadataManager-DFI73J3G.js +10 -0
- package/dist/PRManager-OCSB2HPT.js +14 -0
- package/dist/PromptTemplateManager-5GNF7FCP.js +9 -0
- package/dist/{SettingsManager-XPR4TEQL.js → SettingsManager-CNYBGXDT.js} +3 -3
- package/dist/SettingsMigrationManager-KZKDG66H.js +10 -0
- package/dist/{chunk-OEGECBFS.js → chunk-3PT7RKL5.js} +4 -4
- package/dist/{chunk-WUQQNE63.js → chunk-433MOLAU.js} +44 -7
- package/dist/chunk-433MOLAU.js.map +1 -0
- package/dist/{chunk-LN4H3A6A.js → chunk-53OMUNUN.js} +5 -5
- package/dist/{chunk-THF25ICZ.js → chunk-5F6IWWRS.js} +2 -2
- package/dist/{chunk-P2ZQ5LKB.js → chunk-5IWU3HXE.js} +5 -5
- package/dist/{chunk-QIUJPPJQ.js → chunk-5TXLVEXT.js} +3 -3
- package/dist/{chunk-RFUOIUQF.js → chunk-66BMJ25W.js} +13 -7
- package/dist/chunk-66BMJ25W.js.map +1 -0
- package/dist/{chunk-6UIGZD2N.js → chunk-6MLEBAYZ.js} +2 -2
- package/dist/{chunk-VTXCGKV5.js → chunk-7HIRPCKU.js} +14 -6
- package/dist/chunk-7HIRPCKU.js.map +1 -0
- package/dist/{chunk-UNXRACJ7.js → chunk-7LSSNB7Y.js} +3 -3
- package/dist/{chunk-QHA67Q7A.js → chunk-7Q66W4OH.js} +2 -2
- package/dist/{chunk-RUC7OULH.js → chunk-AEIMYF4P.js} +6 -8
- package/dist/{chunk-RUC7OULH.js.map → chunk-AEIMYF4P.js.map} +1 -1
- package/dist/{chunk-MD6HA5IK.js → chunk-B2UO6EYE.js} +2 -2
- package/dist/{chunk-YZTDGPFB.js → chunk-CFUWQHCJ.js} +2 -2
- package/dist/{chunk-UYWAESOT.js → chunk-F2PWIRV4.js} +3 -3
- package/dist/{chunk-PSFVTBM7.js → chunk-FXDYIV3K.js} +2 -2
- package/dist/{chunk-CDQEK2WD.js → chunk-FXJKNVZW.js} +5 -5
- package/dist/{chunk-3CMGCRB5.js → chunk-HMMO2LDS.js} +3 -3
- package/dist/{chunk-OOU3DKNT.js → chunk-IDUICCZY.js} +2 -2
- package/dist/{chunk-HABINPX2.js → chunk-J7GHNTYK.js} +67 -11
- package/dist/chunk-J7GHNTYK.js.map +1 -0
- package/dist/{chunk-DKQ4SUII.js → chunk-K5G5SFWY.js} +2 -2
- package/dist/chunk-K5G5SFWY.js.map +1 -0
- package/dist/{chunk-KO2FOMHL.js → chunk-LT3SGBR7.js} +2 -2
- package/dist/{chunk-VBFDVGAE.js → chunk-LVLRMP7V.js} +2 -2
- package/dist/{chunk-RNZMHJK7.js → chunk-N4ZJVATC.js} +3 -3
- package/dist/chunk-NXMDEL3F.js +54 -0
- package/dist/chunk-NXMDEL3F.js.map +1 -0
- package/dist/chunk-O7VL5N6S.js +72 -0
- package/dist/chunk-O7VL5N6S.js.map +1 -0
- package/dist/{chunk-S65T4O6I.js → chunk-QPS6TZUW.js} +3 -3
- package/dist/{chunk-RJKMF6BC.js → chunk-SHVB3EFE.js} +3 -3
- package/dist/chunk-VT4PDUYT.js +578 -0
- package/dist/chunk-VT4PDUYT.js.map +1 -0
- package/dist/{chunk-4YTILIIH.js → chunk-VV66DH6T.js} +8 -8
- package/dist/{chunk-GVRO4PWE.js → chunk-XNNXAAZT.js} +6 -6
- package/dist/{chunk-AS2IRKLU.js → chunk-YU5HVI6B.js} +2 -2
- package/dist/{chunk-T5IIUG4Z.js → chunk-Z5BM4JWB.js} +25 -24
- package/dist/chunk-Z5BM4JWB.js.map +1 -0
- package/dist/{chunk-SJ2GZ6RF.js → chunk-ZX3GTM7O.js} +2 -2
- package/dist/{claude-ACVXNB6N.js → claude-H33OQMXO.js} +4 -6
- package/dist/{cleanup-MIDJVSIU.js → cleanup-Y5W3CNUV.js} +20 -22
- package/dist/{cleanup-MIDJVSIU.js.map → cleanup-Y5W3CNUV.js.map} +1 -1
- package/dist/cli.js +125 -81
- package/dist/cli.js.map +1 -1
- package/dist/{color-ZPIIUADB.js → color-4TJ4P5EY.js} +5 -3
- package/dist/{contribute-RS3DO3WP.js → contribute-K7UXBOML.js} +8 -8
- package/dist/{dev-server-ASH7HJVI.js → dev-server-HNBRWGCD.js} +11 -13
- package/dist/{dev-server-ASH7HJVI.js.map → dev-server-HNBRWGCD.js.map} +1 -1
- package/dist/{feedback-RVIGHBJG.js → feedback-567ZH2O7.js} +16 -14
- package/dist/{feedback-RVIGHBJG.js.map → feedback-567ZH2O7.js.map} +1 -1
- package/dist/{git-OQAPUPLP.js → git-OV6ADVO7.js} +6 -6
- package/dist/{ignite-XJALWFAT.js → ignite-3HB3ZBEW.js} +15 -17
- package/dist/{ignite-XJALWFAT.js.map → ignite-3HB3ZBEW.js.map} +1 -1
- package/dist/index.d.ts +54 -35
- package/dist/index.js +377 -276
- package/dist/index.js.map +1 -1
- package/dist/init-CMIRHFSR.js +19 -0
- package/dist/{installation-detector-6R6YOFVZ.js → installation-detector-VXZOCL6P.js} +3 -3
- package/dist/mcp/issue-management-server.js +62 -7
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/neon-helpers-3KBC4A3Y.js +11 -0
- package/dist/{open-KW4NTLXH.js → open-AXE225Z5.js} +11 -13
- package/dist/{open-KW4NTLXH.js.map → open-AXE225Z5.js.map} +1 -1
- package/dist/{projects-QEAEBAT2.js → projects-GVEMCN5R.js} +4 -4
- package/dist/{prompt-A7GGRHSY.js → prompt-3SAZYRUN.js} +3 -3
- package/dist/prompts/session-summary-prompt.txt +58 -4
- package/dist/{rebase-WZHHE5LU.js → rebase-6UIHMUWS.js} +9 -11
- package/dist/{rebase-WZHHE5LU.js.map → rebase-6UIHMUWS.js.map} +1 -1
- package/dist/{recap-33NPZ3ZO.js → recap-XTBNMEMO.js} +12 -19
- package/dist/recap-XTBNMEMO.js.map +1 -0
- package/dist/{remote-73TZ2ADI.js → remote-IJAMOEAP.js} +3 -3
- package/dist/{run-HRYQ7TR7.js → run-H375EYRB.js} +11 -13
- package/dist/{run-HRYQ7TR7.js.map → run-H375EYRB.js.map} +1 -1
- package/dist/{shell-JMU5XTHW.js → shell-33FJCWJQ.js} +9 -11
- package/dist/{shell-JMU5XTHW.js.map → shell-33FJCWJQ.js.map} +1 -1
- package/dist/{summary-4SSGGH7N.js → summary-JUMOCNLR.js} +14 -15
- package/dist/{summary-4SSGGH7N.js.map → summary-JUMOCNLR.js.map} +1 -1
- package/dist/{test-git-6SAIRBUD.js → test-git-CO3BA4BV.js} +6 -6
- package/dist/{test-prefix-RLVRK5ZD.js → test-prefix-HZYSDQYT.js} +6 -6
- package/dist/{test-tabs-3SCJWRKT.js → test-tabs-D3POYOJ5.js} +3 -6
- package/dist/{test-tabs-3SCJWRKT.js.map → test-tabs-D3POYOJ5.js.map} +1 -1
- package/dist/{test-webserver-VPNLAFZ3.js → test-webserver-YVQD42W6.js} +2 -2
- package/dist/{update-LETF5ASC.js → update-5NOHT4SG.js} +4 -4
- package/dist/{update-notifier-H55ZK7NU.js → update-notifier-ARA5SPUW.js} +3 -3
- package/package.json +1 -1
- package/dist/ClaudeContextManager-DQFKIMEP.js +0 -16
- package/dist/ClaudeService-CJS32WG2.js +0 -15
- package/dist/GitHubService-RPM27GWD.js +0 -12
- package/dist/LoomLauncher-4UG2E4CD.js.map +0 -1
- package/dist/MetadataManager-WXUVXKUS.js +0 -10
- package/dist/PRManager-7DSIMCAD.js +0 -16
- package/dist/PromptTemplateManager-72FEOGT6.js +0 -9
- package/dist/SettingsMigrationManager-EH3J2TCN.js +0 -10
- package/dist/chunk-DKQ4SUII.js.map +0 -1
- package/dist/chunk-HABINPX2.js.map +0 -1
- package/dist/chunk-RFUOIUQF.js.map +0 -1
- package/dist/chunk-T5IIUG4Z.js.map +0 -1
- package/dist/chunk-UYVWLISQ.js +0 -113
- package/dist/chunk-UYVWLISQ.js.map +0 -1
- package/dist/chunk-VAYGNQTE.js +0 -234
- package/dist/chunk-VAYGNQTE.js.map +0 -1
- package/dist/chunk-VTXCGKV5.js.map +0 -1
- package/dist/chunk-WUQQNE63.js.map +0 -1
- package/dist/chunk-Z5NXYJIG.js +0 -207
- package/dist/chunk-Z5NXYJIG.js.map +0 -1
- package/dist/init-F6PFMSU5.js +0 -21
- package/dist/neon-helpers-L5CXQ5CT.js +0 -11
- package/dist/recap-33NPZ3ZO.js.map +0 -1
- /package/dist/{BranchNamingService-GCCWB3LK.js.map → BranchNamingService-B5PVRR7F.js.map} +0 -0
- /package/dist/{ClaudeContextManager-DQFKIMEP.js.map → ClaudeContextManager-PQ46VILL.js.map} +0 -0
- /package/dist/{ClaudeService-CJS32WG2.js.map → ClaudeService-6OMO552H.js.map} +0 -0
- /package/dist/{GitHubService-RPM27GWD.js.map → GitHubService-S2OGUTDR.js.map} +0 -0
- /package/dist/{MetadataManager-WXUVXKUS.js.map → MetadataManager-DFI73J3G.js.map} +0 -0
- /package/dist/{PRManager-7DSIMCAD.js.map → PRManager-OCSB2HPT.js.map} +0 -0
- /package/dist/{PromptTemplateManager-72FEOGT6.js.map → PromptTemplateManager-5GNF7FCP.js.map} +0 -0
- /package/dist/{SettingsManager-XPR4TEQL.js.map → SettingsManager-CNYBGXDT.js.map} +0 -0
- /package/dist/{SettingsMigrationManager-EH3J2TCN.js.map → SettingsMigrationManager-KZKDG66H.js.map} +0 -0
- /package/dist/{chunk-OEGECBFS.js.map → chunk-3PT7RKL5.js.map} +0 -0
- /package/dist/{chunk-LN4H3A6A.js.map → chunk-53OMUNUN.js.map} +0 -0
- /package/dist/{chunk-THF25ICZ.js.map → chunk-5F6IWWRS.js.map} +0 -0
- /package/dist/{chunk-P2ZQ5LKB.js.map → chunk-5IWU3HXE.js.map} +0 -0
- /package/dist/{chunk-QIUJPPJQ.js.map → chunk-5TXLVEXT.js.map} +0 -0
- /package/dist/{chunk-6UIGZD2N.js.map → chunk-6MLEBAYZ.js.map} +0 -0
- /package/dist/{chunk-UNXRACJ7.js.map → chunk-7LSSNB7Y.js.map} +0 -0
- /package/dist/{chunk-QHA67Q7A.js.map → chunk-7Q66W4OH.js.map} +0 -0
- /package/dist/{chunk-MD6HA5IK.js.map → chunk-B2UO6EYE.js.map} +0 -0
- /package/dist/{chunk-YZTDGPFB.js.map → chunk-CFUWQHCJ.js.map} +0 -0
- /package/dist/{chunk-UYWAESOT.js.map → chunk-F2PWIRV4.js.map} +0 -0
- /package/dist/{chunk-PSFVTBM7.js.map → chunk-FXDYIV3K.js.map} +0 -0
- /package/dist/{chunk-CDQEK2WD.js.map → chunk-FXJKNVZW.js.map} +0 -0
- /package/dist/{chunk-3CMGCRB5.js.map → chunk-HMMO2LDS.js.map} +0 -0
- /package/dist/{chunk-OOU3DKNT.js.map → chunk-IDUICCZY.js.map} +0 -0
- /package/dist/{chunk-KO2FOMHL.js.map → chunk-LT3SGBR7.js.map} +0 -0
- /package/dist/{chunk-VBFDVGAE.js.map → chunk-LVLRMP7V.js.map} +0 -0
- /package/dist/{chunk-RNZMHJK7.js.map → chunk-N4ZJVATC.js.map} +0 -0
- /package/dist/{chunk-S65T4O6I.js.map → chunk-QPS6TZUW.js.map} +0 -0
- /package/dist/{chunk-RJKMF6BC.js.map → chunk-SHVB3EFE.js.map} +0 -0
- /package/dist/{chunk-4YTILIIH.js.map → chunk-VV66DH6T.js.map} +0 -0
- /package/dist/{chunk-GVRO4PWE.js.map → chunk-XNNXAAZT.js.map} +0 -0
- /package/dist/{chunk-AS2IRKLU.js.map → chunk-YU5HVI6B.js.map} +0 -0
- /package/dist/{chunk-SJ2GZ6RF.js.map → chunk-ZX3GTM7O.js.map} +0 -0
- /package/dist/{claude-ACVXNB6N.js.map → claude-H33OQMXO.js.map} +0 -0
- /package/dist/{color-ZPIIUADB.js.map → color-4TJ4P5EY.js.map} +0 -0
- /package/dist/{contribute-RS3DO3WP.js.map → contribute-K7UXBOML.js.map} +0 -0
- /package/dist/{git-OQAPUPLP.js.map → git-OV6ADVO7.js.map} +0 -0
- /package/dist/{init-F6PFMSU5.js.map → init-CMIRHFSR.js.map} +0 -0
- /package/dist/{installation-detector-6R6YOFVZ.js.map → installation-detector-VXZOCL6P.js.map} +0 -0
- /package/dist/{neon-helpers-L5CXQ5CT.js.map → neon-helpers-3KBC4A3Y.js.map} +0 -0
- /package/dist/{projects-QEAEBAT2.js.map → projects-GVEMCN5R.js.map} +0 -0
- /package/dist/{prompt-A7GGRHSY.js.map → prompt-3SAZYRUN.js.map} +0 -0
- /package/dist/{remote-73TZ2ADI.js.map → remote-IJAMOEAP.js.map} +0 -0
- /package/dist/{test-git-6SAIRBUD.js.map → test-git-CO3BA4BV.js.map} +0 -0
- /package/dist/{test-prefix-RLVRK5ZD.js.map → test-prefix-HZYSDQYT.js.map} +0 -0
- /package/dist/{test-webserver-VPNLAFZ3.js.map → test-webserver-YVQD42W6.js.map} +0 -0
- /package/dist/{update-LETF5ASC.js.map → update-5NOHT4SG.js.map} +0 -0
- /package/dist/{update-notifier-H55ZK7NU.js.map → update-notifier-ARA5SPUW.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/env.ts","../src/utils/logger.ts","../src/utils/terminal.ts"],"sourcesContent":["import path from 'path'\nimport dotenvFlow, { type DotenvFlowConfigOptions } from 'dotenv-flow'\nimport { logger } from './logger.js'\n\n/**\n * Parse .env file content into key-value map\n * Handles comments, empty lines, quoted/unquoted values, multiline values\n */\nexport function parseEnvFile(content: string): Map<string, string> {\n const envMap = new Map<string, string>()\n const lines = content.split('\\n')\n\n for (const line of lines) {\n const trimmedLine = line.trim()\n\n // Skip empty lines and comments\n if (!trimmedLine || trimmedLine.startsWith('#')) {\n continue\n }\n\n // Remove 'export ' prefix if present\n const cleanLine = trimmedLine.startsWith('export ')\n ? trimmedLine.substring(7)\n : trimmedLine\n\n // Find the first equals sign\n const equalsIndex = cleanLine.indexOf('=')\n if (equalsIndex === -1) {\n continue\n }\n\n const key = cleanLine.substring(0, equalsIndex).trim()\n let value = cleanLine.substring(equalsIndex + 1)\n\n // Handle quoted values\n if (\n (value.startsWith('\"') && value.endsWith('\"')) ||\n (value.startsWith(\"'\") && value.endsWith(\"'\"))\n ) {\n value = value.substring(1, value.length - 1)\n // Unescape quotes\n value = value.replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\")\n // Unescape newlines\n value = value.replace(/\\\\n/g, '\\n')\n }\n\n if (key) {\n envMap.set(key, value)\n }\n }\n\n return envMap\n}\n\n/**\n * Format environment variable as line for .env file\n * Always quotes values and escapes internal quotes\n */\nexport function formatEnvLine(key: string, value: string): string {\n // Escape quotes and newlines in the value\n const escapedValue = value\n .replace(/\"/g, '\\\\\"')\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r')\n\n return `${key}=\"${escapedValue}\"`\n}\n\n/**\n * Validate environment variable name and value\n */\nexport function validateEnvVariable(\n key: string,\n _value?: string\n): { valid: boolean; error?: string } {\n if (!key || key.length === 0) {\n return {\n valid: false,\n error: 'Environment variable key cannot be empty',\n }\n }\n\n if (!isValidEnvKey(key)) {\n return {\n valid: false,\n error: `Invalid environment variable name: ${key}. Must start with a letter or underscore and contain only letters, numbers, and underscores.`,\n }\n }\n\n // Values can be any string, including empty\n return { valid: true }\n}\n\n/**\n * Normalize line endings for cross-platform compatibility\n */\nexport function normalizeLineEndings(content: string): string {\n return content.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n')\n}\n\n/**\n * Extract port from .env file if present\n */\nexport function extractPort(envContent: Map<string, string>): number | null {\n const portValue = envContent.get('PORT')\n if (!portValue) {\n return null\n }\n\n const port = parseInt(portValue, 10)\n if (isNaN(port)) {\n return null\n }\n\n return port\n}\n\n/**\n * Check if environment variable key is valid\n */\nexport function isValidEnvKey(key: string): boolean {\n if (!key || key.length === 0) {\n return false\n }\n\n // Must start with letter or underscore, followed by letters, numbers, or underscores\n const validKeyRegex = /^[A-Za-z_][A-Za-z0-9_]*$/\n return validKeyRegex.test(key)\n}\n\n/**\n * Load environment variables using dotenv-flow\n * Supports environment-specific files (.env.development, .env.production, etc.)\n * and local overrides (.env.local, .env.development.local)\n */\nexport function loadEnvIntoProcess(options?: {\n path?: string\n nodeEnv?: string\n defaultNodeEnv?: string\n}): { parsed?: Record<string, string>; error?: Error } {\n logger.debug('Loading environment variables with dotenv-flow', {\n options: {\n path: options?.path ?? 'current working directory',\n nodeEnv: options?.nodeEnv ?? 'not specified',\n defaultNodeEnv: options?.defaultNodeEnv ?? 'development (default)'\n }\n })\n\n const configOptions: Partial<DotenvFlowConfigOptions> = {\n silent: true, // Don't throw errors if .env files are missing\n }\n\n // Only add defined values to avoid TypeScript strict type issues\n if (options?.path !== undefined) {\n configOptions.path = options.path\n logger.debug(`Using custom path: ${options.path}`)\n }\n if (options?.nodeEnv !== undefined) {\n configOptions.node_env = options.nodeEnv\n logger.debug(`Using NODE_ENV: ${options.nodeEnv}`)\n }\n if (options?.defaultNodeEnv !== undefined) {\n configOptions.default_node_env = options.defaultNodeEnv\n logger.debug(`Using default NODE_ENV: ${options.defaultNodeEnv}`)\n } else {\n configOptions.default_node_env = 'development'\n logger.debug('Using default NODE_ENV: development')\n }\n\n logger.debug('dotenv-flow config options:', configOptions)\n\n const result = dotenvFlow.config(configOptions)\n\n const returnValue: { parsed?: Record<string, string>; error?: Error } = {}\n\n if (result.parsed) {\n returnValue.parsed = result.parsed as Record<string, string>\n const variableCount = Object.keys(result.parsed).length\n logger.debug(`Successfully loaded ${variableCount} environment variables`)\n } else {\n logger.debug('No environment variables were parsed')\n }\n\n if (result.error) {\n returnValue.error = result.error\n logger.debug('dotenv-flow returned an error', {\n error: result.error.message,\n name: result.error.name\n })\n } else {\n logger.debug('dotenv-flow completed without errors')\n }\n\n return returnValue\n}\n\n/**\n * Check if an error from loadEnvIntoProcess indicates no .env files were found\n * This is a harmless condition that shouldn't be logged as a warning\n */\nexport function isNoEnvFilesFoundError(error: Error): boolean {\n return error.message.startsWith('no \".env*\" files matching pattern')\n}\n\n/**\n * Load environment variables for a specific workspace\n * Automatically determines environment based on NODE_ENV or defaults to development\n */\nexport function loadWorkspaceEnv(workspacePath: string): {\n parsed?: Record<string, string>\n error?: Error\n} {\n const nodeEnv = process.env.NODE_ENV ?? 'development'\n\n logger.debug('Loading workspace environment variables', {\n workspacePath,\n detectedNodeEnv: nodeEnv,\n processNodeEnv: process.env.NODE_ENV ?? 'not set'\n })\n\n return loadEnvIntoProcess({\n path: workspacePath,\n nodeEnv: nodeEnv,\n defaultNodeEnv: 'development'\n })\n}\n\n// CONSTANT: Always use 'development' per critical constraint, unless overridden\nconst DOTENV_FLOW_NODE_ENV = process.env.DOTENV_FLOW_NODE_ENV ?? 'development'\n\n/**\n * Get dotenv-flow files in precedence order (lowest to highest)\n * Always uses 'development' as NODE_ENV per constraint\n */\nexport function getDotenvFlowFiles(): string[] {\n return [\n '.env',\n '.env.local',\n `.env.${DOTENV_FLOW_NODE_ENV}`,\n `.env.${DOTENV_FLOW_NODE_ENV}.local`\n ]\n}\n\n/**\n * Map a file to its \"local\" equivalent for git-safe writes\n * .env -> .env.local\n * .env.{NODE_ENV} -> .env.{NODE_ENV}.local\n * Already local files return unchanged\n */\nexport function getLocalEquivalent(filename: string): string {\n // Already a .local file\n if (filename.endsWith('.local')) {\n return filename\n }\n return `${filename}.local`\n}\n\n/**\n * Find the appropriate env file to write a database URL variable to\n * Considers dotenv-flow precedence and git tracking status\n * Returns path relative to workspacePath\n *\n * Algorithm:\n * 1. Search files in reverse precedence order (highest first)\n * 2. Find first file containing the variable\n * 3. If tracked by git, return its .local equivalent\n * 4. If not tracked, return the file itself\n * 5. If not found anywhere, return '.env.local' (safe default)\n */\nexport async function findEnvFileForDatabaseUrl(\n workspacePath: string,\n variableName: string,\n isFileTracked: (filePath: string, cwd: string) => Promise<boolean>,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<string> {\n // Find the highest-precedence file containing the variable\n const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable)\n\n if (file === null) {\n // Variable not found anywhere - use safe default\n return '.env.local'\n }\n\n // Found the variable - check git tracking\n const isTracked = await isFileTracked(file, workspacePath)\n if (isTracked) {\n // Return .local equivalent for git safety\n return getLocalEquivalent(file)\n }\n\n return file\n}\n\n/**\n * Build shell source commands for all existing dotenv-flow files\n * Returns commands in precedence order (later overrides earlier)\n */\nexport async function buildEnvSourceCommands(\n workspacePath: string,\n fileExists: (filePath: string) => Promise<boolean>\n): Promise<string[]> {\n const files = getDotenvFlowFiles()\n const commands: string[] = []\n\n for (const file of files) {\n const fullPath = path.join(workspacePath, file)\n const exists = await fileExists(fullPath)\n if (exists) {\n commands.push(`source ${file}`)\n }\n }\n\n return commands\n}\n\n/**\n * Find the highest-precedence env file containing a variable\n * Searches all dotenv-flow files in reverse precedence order (highest first)\n * Returns the relative filename if found, null otherwise\n */\nexport async function findEnvFileContainingVariable(\n workspacePath: string,\n variableName: string,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<string | null> {\n const files = getDotenvFlowFiles().reverse() // highest precedence first\n\n for (const file of files) {\n const fullPath = path.join(workspacePath, file)\n\n // Skip if file doesn't exist\n if (!(await fileExists(fullPath))) {\n continue\n }\n\n // Check if file contains the variable\n const value = await getEnvVariable(fullPath, variableName)\n if (value !== null) {\n return file\n }\n }\n\n return null\n}\n\n/**\n * Check if a variable exists in any dotenv-flow file\n * Searches all dotenv-flow files (.env, .env.local, .env.{NODE_ENV}, .env.{NODE_ENV}.local)\n * Returns true if variable is found in any file, false otherwise\n */\nexport async function hasVariableInAnyEnvFile(\n workspacePath: string,\n variableName: string,\n fileExists: (filePath: string) => Promise<boolean>,\n getEnvVariable: (filePath: string, varName: string) => Promise<string | null>\n): Promise<boolean> {\n const file = await findEnvFileContainingVariable(workspacePath, variableName, fileExists, getEnvVariable)\n return file !== null\n}\n","// Lines 1-5: Imports\nimport chalk, { Chalk } from 'chalk'\nimport { detectDarkMode, type ThemeMode } from './terminal.js'\n\n// Lines 7-17: Type definitions\nexport interface LoggerOptions {\n prefix?: string\n timestamp?: boolean\n silent?: boolean\n forceColor?: boolean | undefined | null\n debug?: boolean\n}\n\nexport interface Logger {\n info: (message: string, ...args: unknown[]) => void\n success: (message: string, ...args: unknown[]) => void\n warn: (message: string, ...args: unknown[]) => void\n error: (message: string, ...args: unknown[]) => void\n debug: (message: string, ...args: unknown[]) => void\n setDebug: (enabled: boolean) => void\n isDebugEnabled: () => boolean\n stdout: NodeJS.WriteStream // Stream for progress output (stdout normally, stderr in JSON mode)\n}\n\n// Lines 19-29: Stream-specific chalk instances\nconst stdoutChalk = new Chalk({ level: chalk.level })\nconst stderrChalk = new Chalk({ level: chalk.level })\n\n// Lines 31-60: Theme-aware color selection\nlet currentThemeMode: ThemeMode = 'light'\n\n/**\n * Initialize theme mode detection\n * This is called automatically on module load\n */\nasync function initializeThemeMode(): Promise<void> {\n try {\n currentThemeMode = await detectDarkMode()\n } catch {\n // Default to light mode on error\n currentThemeMode = 'light'\n }\n}\n\n// Initialize theme mode on module load (non-blocking)\nvoid initializeThemeMode()\n\n/**\n * Get color function based on current theme mode\n * Light mode uses standard colors, dark mode uses brighter/more saturated variants\n */\nfunction getInfoColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.cyan : chalkInstance.blue\n}\n\nfunction getSuccessColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.greenBright : chalkInstance.green\n}\n\nfunction getWarnColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.yellowBright : chalkInstance.yellow\n}\n\nfunction getErrorColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.redBright : chalkInstance.red\n}\n\nfunction getDebugColor(chalkInstance: InstanceType<typeof Chalk>): (str: string) => string {\n return currentThemeMode === 'dark' ? chalkInstance.gray : chalkInstance.gray\n}\n\n// Lines 31-45: Helper functions\nfunction formatMessage(message: string, ...args: unknown[]): string {\n // Convert args to strings and append to message\n const formattedArgs = args.map(arg =>\n typeof arg === 'object' ? JSON.stringify(arg, null, 2) : String(arg)\n )\n return formattedArgs.length > 0 ? `${message} ${formattedArgs.join(' ')}` : message\n}\n\nfunction formatWithEmoji(message: string, emoji: string, colorFn: (str: string) => string): string {\n if (message.trim()) {\n return colorFn(`${emoji} ${message}`)\n } else {\n return ''\n }\n}\n\nlet globalDebugEnabled = false\n\n// Lines 47-96: Main logger implementation\n/* eslint-disable no-console */\nexport const logger: Logger = {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🗂️ ', getInfoColor(stdoutChalk))\n console.log(output)\n },\n\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '✅', getSuccessColor(stdoutChalk))\n console.log(output)\n },\n\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '⚠️ ', getWarnColor(stderrChalk))\n console.error(output)\n },\n\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '❌', getErrorColor(stderrChalk))\n console.error(output)\n },\n\n debug: (message: string, ...args: unknown[]): void => {\n if (globalDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const output = formatWithEmoji(formatted, '🔍', getDebugColor(stdoutChalk))\n console.log(output)\n }\n },\n\n setDebug: (enabled: boolean): void => {\n globalDebugEnabled = enabled\n },\n\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n\n stdout: process.stdout\n}\n/* eslint-enable no-console */\n\n// Lines 98-145: Factory function for custom logger instances\nexport function createLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, silent = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customStdoutChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stdoutChalk\n const customStderrChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n if (silent) {\n // Return no-op logger when silent\n return {\n info: (): void => {},\n success: (): void => {},\n warn: (): void => {},\n error: (): void => {},\n debug: (): void => {},\n setDebug: (): void => {},\n isDebugEnabled: (): boolean => {\n return false\n },\n stdout: process.stdout\n }\n }\n\n /* eslint-disable no-console */\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', getInfoColor(customStdoutChalk))\n console.log(output)\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', getSuccessColor(customStdoutChalk))\n console.log(output)\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', getWarnColor(customStderrChalk))\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', getErrorColor(customStderrChalk))\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', getDebugColor(customStdoutChalk))\n console.log(output)\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stdout\n }\n /* eslint-enable no-console */\n}\n\n// Lines 147-200: Factory function for stderr-only logger (for JSON mode)\n/**\n * Creates a logger that redirects all output to stderr.\n * Use this in JSON mode so progress messages don't pollute stdout.\n * The JSON output can then be cleanly piped.\n */\nexport function createStderrLogger(options: LoggerOptions = {}): Logger {\n const { prefix = '', timestamp = false, forceColor, debug = globalDebugEnabled } = options\n\n // Local debug flag for this logger instance\n let localDebugEnabled = debug\n\n // Create chalk instances with forced color if needed\n const customChalk = forceColor !== undefined\n ? new Chalk({ level: forceColor ? 3 : 0 })\n : stderrChalk\n\n const prefixStr = prefix ? `[${prefix}] ` : ''\n const getTimestamp = (): string => timestamp ? `[${new Date().toISOString()}] ` : ''\n\n return {\n info: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🗂️ ', getInfoColor(customChalk))\n console.error(output) // Redirect to stderr\n },\n success: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '✅', getSuccessColor(customChalk))\n console.error(output) // Redirect to stderr\n },\n warn: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '⚠️ ', getWarnColor(customChalk))\n console.error(output)\n },\n error: (message: string, ...args: unknown[]): void => {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '❌', getErrorColor(customChalk))\n console.error(output)\n },\n debug: (message: string, ...args: unknown[]): void => {\n if (localDebugEnabled) {\n const formatted = formatMessage(message, ...args)\n const fullMessage = `${getTimestamp()}${prefixStr}${formatted}`\n const output = formatWithEmoji(fullMessage, '🔍', getDebugColor(customChalk))\n console.error(output) // Redirect to stderr\n }\n },\n setDebug: (enabled: boolean): void => {\n localDebugEnabled = enabled\n },\n isDebugEnabled: (): boolean => {\n return globalDebugEnabled\n },\n stdout: process.stderr // Use stderr for progress output in JSON mode\n }\n}\n\n/**\n * Set the theme mode for logger colors\n * This is useful for testing or overriding auto-detection\n *\n * @param mode - Theme mode to use ('light' or 'dark')\n */\nexport function setThemeMode(mode: ThemeMode): void {\n currentThemeMode = mode\n}\n\n/**\n * Get the current theme mode\n *\n * @returns Current theme mode\n */\nexport function getThemeMode(): ThemeMode {\n return currentThemeMode\n}\n\n// Default export\nexport default logger\n","import { execa } from 'execa'\nimport { existsSync } from 'node:fs'\nimport type { Platform } from '../types/index.js'\nimport { buildEnvSourceCommands } from './env.js'\n\nexport interface TerminalWindowOptions {\n\tworkspacePath?: string\n\tcommand?: string\n\tbackgroundColor?: { r: number; g: number; b: number }\n\tport?: number\n\tincludeEnvSetup?: boolean // source .env\n\tincludePortExport?: boolean // export PORT=<port>\n\ttitle?: string // Terminal tab title\n}\n\n/**\n * Detect current platform\n */\nexport function detectPlatform(): Platform {\n\tconst platform = process.platform\n\tif (platform === 'darwin') return 'darwin'\n\tif (platform === 'linux') return 'linux'\n\tif (platform === 'win32') return 'win32'\n\treturn 'unsupported'\n}\n\n/**\n * Theme mode for color palette selection\n */\nexport type ThemeMode = 'light' | 'dark'\n\n/**\n * Detect macOS dark mode using defaults command\n * Returns 'light' as default for non-macOS platforms or detection failures\n *\n * Uses `defaults read -g AppleInterfaceStyle` which returns \"Dark\" in dark mode\n * and errors (exit code 1) in light mode. This approach doesn't require\n * System Events permission unlike AppleScript.\n */\nexport async function detectDarkMode(): Promise<ThemeMode> {\n\tconst platform = detectPlatform()\n\tif (platform !== 'darwin') {\n\t\treturn 'light'\n\t}\n\n\ttry {\n\t\tconst result = await execa('defaults', ['read', '-g', 'AppleInterfaceStyle'])\n\t\treturn result.stdout.trim().toLowerCase() === 'dark' ? 'dark' : 'light'\n\t} catch {\n\t\t// defaults command errors when AppleInterfaceStyle is not set (light mode)\n\t\treturn 'light'\n\t}\n}\n\n/**\n * Detect if iTerm2 is installed on macOS\n * Returns false on non-macOS platforms\n */\nexport async function detectITerm2(): Promise<boolean> {\n\tconst platform = detectPlatform()\n\tif (platform !== 'darwin') return false\n\n\t// Check if iTerm.app exists at standard location\n\treturn existsSync('/Applications/iTerm.app')\n}\n\n/**\n * Open new terminal window with specified options\n * Currently supports macOS only\n */\nexport async function openTerminalWindow(\n\toptions: TerminalWindowOptions\n): Promise<void> {\n\tconst platform = detectPlatform()\n\n\tif (platform !== 'darwin') {\n\t\tthrow new Error(\n\t\t\t`Terminal window launching not yet supported on ${platform}. ` +\n\t\t\t\t`Currently only macOS is supported.`\n\t\t)\n\t}\n\n\t// Detect if iTerm2 is available\n\tconst hasITerm2 = await detectITerm2()\n\n\t// Build appropriate AppleScript based on terminal availability\n\tconst applescript = hasITerm2\n\t\t? await buildITerm2SingleTabScript(options)\n\t\t: await buildAppleScript(options)\n\n\ttry {\n\t\tawait execa('osascript', ['-e', applescript])\n\n\t\t// Activate the appropriate terminal application (only needed for Terminal.app)\n\t\t// iTerm2 script includes its own activation\n\t\tif (!hasITerm2) {\n\t\t\tawait execa('osascript', ['-e', 'tell application \"Terminal\" to activate'])\n\t\t}\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`Failed to open terminal window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t)\n\t}\n}\n\n/**\n * Build AppleScript for macOS Terminal.app\n */\nasync function buildAppleScript(options: TerminalWindowOptions): Promise<string> {\n\tconst {\n\t\tworkspacePath,\n\t\tcommand,\n\t\tbackgroundColor,\n\t\tport,\n\t\tincludeEnvSetup,\n\t\tincludePortExport,\n\t} = options\n\n\t// Build command sequence\n\tconst commands: string[] = []\n\n\t// Navigate to workspace\n\tif (workspacePath) {\n\t\tcommands.push(`cd '${escapePathForAppleScript(workspacePath)}'`)\n\t}\n\n\t// Source all dotenv-flow files\n\tif (includeEnvSetup && workspacePath) {\n\t\tconst sourceCommands = await buildEnvSourceCommands(\n\t\t\tworkspacePath,\n\t\t\tasync (p) => existsSync(p)\n\t\t)\n\t\tcommands.push(...sourceCommands)\n\t}\n\n\t// Export PORT variable\n\tif (includePortExport && port !== undefined) {\n\t\tcommands.push(`export PORT=${port}`)\n\t}\n\n\t// Add custom command\n\tif (command) {\n\t\tcommands.push(command)\n\t}\n\n\t// Join with &&\n\tconst fullCommand = commands.join(' && ')\n\n\t// Prefix with space to prevent shell history pollution\n\t// Most shells (bash/zsh) ignore commands starting with space when HISTCONTROL=ignorespace\n\tconst historyFreeCommand = ` ${fullCommand}`\n\n\t// Build AppleScript\n\tlet script = `tell application \"Terminal\"\\n`\n\tscript += ` set newTab to do script \"${escapeForAppleScript(historyFreeCommand)}\"\\n`\n\n\t// Apply background color if provided\n\tif (backgroundColor) {\n\t\tconst { r, g, b } = backgroundColor\n\t\t// Convert 8-bit RGB (0-255) to 16-bit RGB (0-65535)\n\t\tscript += ` set background color of newTab to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\tscript += `end tell`\n\n\treturn script\n}\n\n/**\n * Escape path for AppleScript string\n * Single quotes in path need special escaping\n */\nfunction escapePathForAppleScript(path: string): string {\n\t// Replace single quote with '\\''\n\treturn path.replace(/'/g, \"'\\\\''\")\n}\n\n/**\n * Escape command for AppleScript do script\n * Must handle double quotes and backslashes\n */\nfunction escapeForAppleScript(command: string): string {\n\treturn (\n\t\tcommand\n\t\t\t.replace(/\\\\/g, '\\\\\\\\') // Escape backslashes\n\t\t\t.replace(/\"/g, '\\\\\"') // Escape double quotes\n\t)\n}\n\n/**\n * Build iTerm2 AppleScript for single tab\n */\nasync function buildITerm2SingleTabScript(options: TerminalWindowOptions): Promise<string> {\n\tconst command = await buildCommandSequence(options)\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set s1 to current session of current window\\n\\n'\n\n\t// Set background color\n\tif (options.backgroundColor) {\n\t\tconst { r, g, b } = options.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\t// Execute command\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\t// Set session name (tab title)\n\tif (options.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t}\n\n\t// Activate iTerm2\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\n\treturn script\n}\n\n/**\n * Build command sequence for terminal\n */\nasync function buildCommandSequence(options: TerminalWindowOptions): Promise<string> {\n\tconst {\n\t\tworkspacePath,\n\t\tcommand,\n\t\tport,\n\t\tincludeEnvSetup,\n\t\tincludePortExport,\n\t} = options\n\n\tconst commands: string[] = []\n\n\t// Navigate to workspace\n\tif (workspacePath) {\n\t\tcommands.push(`cd '${escapePathForAppleScript(workspacePath)}'`)\n\t}\n\n\t// Source all dotenv-flow files\n\tif (includeEnvSetup && workspacePath) {\n\t\tconst sourceCommands = await buildEnvSourceCommands(\n\t\t\tworkspacePath,\n\t\t\tasync (p) => existsSync(p)\n\t\t)\n\t\tcommands.push(...sourceCommands)\n\t}\n\n\t// Export PORT variable\n\tif (includePortExport && port !== undefined) {\n\t\tcommands.push(`export PORT=${port}`)\n\t}\n\n\t// Add custom command\n\tif (command) {\n\t\tcommands.push(command)\n\t}\n\n\t// Join with &&\n\tconst fullCommand = commands.join(' && ')\n\n\t// Prefix with space to prevent shell history pollution\n\treturn ` ${fullCommand}`\n}\n\n/**\n * Build iTerm2 AppleScript for multiple tabs (2+) in single window\n */\nasync function buildITerm2MultiTabScript(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<string> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('buildITerm2MultiTabScript requires at least 2 terminal options')\n\t}\n\n\tlet script = 'tell application id \"com.googlecode.iterm2\"\\n'\n\tscript += ' create window with default profile\\n'\n\tscript += ' set newWindow to current window\\n'\n\n\t// First tab\n\tconst options1 = optionsArray[0]\n\tif (!options1) {\n\t\tthrow new Error('First terminal option is undefined')\n\t}\n\tconst command1 = await buildCommandSequence(options1)\n\n\tscript += ' set s1 to current session of newWindow\\n\\n'\n\n\t// Set background color for first tab\n\tif (options1.backgroundColor) {\n\t\tconst { r, g, b } = options1.backgroundColor\n\t\tscript += ` set background color of s1 to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t}\n\n\t// Execute command in first tab\n\tscript += ` tell s1 to write text \"${escapeForAppleScript(command1)}\"\\n\\n`\n\n\t// Set tab title for first tab\n\tif (options1.title) {\n\t\tscript += ` set name of s1 to \"${escapeForAppleScript(options1.title)}\"\\n\\n`\n\t}\n\n\t// Subsequent tabs (2, 3, ...)\n\tfor (let i = 1; i < optionsArray.length; i++) {\n\t\tconst options = optionsArray[i]\n\t\tif (!options) {\n\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t}\n\t\tconst command = await buildCommandSequence(options)\n\t\tconst sessionVar = `s${i + 1}`\n\n\t\t// Create tab\n\t\tscript += ' tell newWindow\\n'\n\t\tscript += ` set newTab${i} to (create tab with default profile)\\n`\n\t\tscript += ' end tell\\n'\n\t\tscript += ` set ${sessionVar} to current session of newTab${i}\\n\\n`\n\n\t\t// Set background color\n\t\tif (options.backgroundColor) {\n\t\t\tconst { r, g, b } = options.backgroundColor\n\t\t\tscript += ` set background color of ${sessionVar} to {${Math.round(r * 257)}, ${Math.round(g * 257)}, ${Math.round(b * 257)}}\\n`\n\t\t}\n\n\t\t// Execute command\n\t\tscript += ` tell ${sessionVar} to write text \"${escapeForAppleScript(command)}\"\\n\\n`\n\n\t\t// Set tab title\n\t\tif (options.title) {\n\t\t\tscript += ` set name of ${sessionVar} to \"${escapeForAppleScript(options.title)}\"\\n\\n`\n\t\t}\n\t}\n\n\t// Activate iTerm2\n\tscript += ' activate\\n'\n\tscript += 'end tell'\n\n\treturn script\n}\n\n/**\n * Open multiple terminal windows/tabs (2+) with specified options\n * If iTerm2 is available on macOS, creates single window with multiple tabs\n * Otherwise falls back to multiple separate Terminal.app windows\n */\nexport async function openMultipleTerminalWindows(\n\toptionsArray: TerminalWindowOptions[]\n): Promise<void> {\n\tif (optionsArray.length < 2) {\n\t\tthrow new Error('openMultipleTerminalWindows requires at least 2 terminal options. Use openTerminalWindow for single terminal.')\n\t}\n\n\tconst platform = detectPlatform()\n\n\tif (platform !== 'darwin') {\n\t\tthrow new Error(\n\t\t\t`Terminal window launching not yet supported on ${platform}. ` +\n\t\t\t\t`Currently only macOS is supported.`\n\t\t)\n\t}\n\n\t// Detect if iTerm2 is available\n\tconst hasITerm2 = await detectITerm2()\n\n\tif (hasITerm2) {\n\t\t// Use iTerm2 with multiple tabs in single window\n\t\tconst applescript = await buildITerm2MultiTabScript(optionsArray)\n\n\t\ttry {\n\t\t\tawait execa('osascript', ['-e', applescript])\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to open iTerm2 window: ${error instanceof Error ? error.message : 'Unknown error'}`\n\t\t\t)\n\t\t}\n\t} else {\n\t\t// Fall back to multiple Terminal.app windows\n\t\tfor (let i = 0; i < optionsArray.length; i++) {\n\t\t\tconst options = optionsArray[i]\n\t\t\tif (!options) {\n\t\t\t\tthrow new Error(`Terminal option at index ${i} is undefined`)\n\t\t\t}\n\t\t\tawait openTerminalWindow(options)\n\n\t\t\t// Brief pause between terminals (except after last one)\n\t\t\tif (i < optionsArray.length - 1) {\n\t\t\t\t// eslint-disable-next-line no-undef\n\t\t\t\tawait new Promise<void>((resolve) => setTimeout(resolve, 1000))\n\t\t\t}\n\t\t}\n\t}\n}\n\n/**\n * Open dual terminal windows/tabs with specified options\n * If iTerm2 is available on macOS, creates single window with two tabs\n * Otherwise falls back to two separate Terminal.app windows\n */\nexport async function openDualTerminalWindow(\n\toptions1: TerminalWindowOptions,\n\toptions2: TerminalWindowOptions\n): Promise<void> {\n\t// Delegate to openMultipleTerminalWindows for consistency\n\tawait openMultipleTerminalWindows([options1, options2])\n}\n"],"mappings":"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","names":["path"]}
|
|
@@ -1,26 +1,26 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
SettingsMigrationManager
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-F2PWIRV4.js";
|
|
5
5
|
import {
|
|
6
6
|
GitWorktreeManager
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-HMMO2LDS.js";
|
|
8
8
|
import {
|
|
9
9
|
parseGitRemotes
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-FXDYIV3K.js";
|
|
11
11
|
import {
|
|
12
12
|
PromptTemplateManager
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-K5G5SFWY.js";
|
|
14
14
|
import {
|
|
15
15
|
isFileGitignored
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-53OMUNUN.js";
|
|
17
17
|
import {
|
|
18
18
|
detectClaudeCli,
|
|
19
19
|
launchClaude
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-AEIMYF4P.js";
|
|
21
21
|
import {
|
|
22
22
|
logger
|
|
23
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-VT4PDUYT.js";
|
|
24
24
|
|
|
25
25
|
// src/lib/ShellCompletion.ts
|
|
26
26
|
import omelette from "omelette";
|
|
@@ -699,4 +699,4 @@ export {
|
|
|
699
699
|
ShellCompletion,
|
|
700
700
|
InitCommand
|
|
701
701
|
};
|
|
702
|
-
//# sourceMappingURL=chunk-
|
|
702
|
+
//# sourceMappingURL=chunk-VV66DH6T.js.map
|
|
@@ -4,20 +4,20 @@ import {
|
|
|
4
4
|
findMainWorktreePathWithSettings,
|
|
5
5
|
findWorktreeForBranch,
|
|
6
6
|
getMergeTargetBranch
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-53OMUNUN.js";
|
|
8
8
|
import {
|
|
9
9
|
SettingsManager
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IDUICCZY.js";
|
|
11
11
|
import {
|
|
12
12
|
MetadataManager
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-CFUWQHCJ.js";
|
|
14
14
|
import {
|
|
15
15
|
detectClaudeCli,
|
|
16
16
|
launchClaude
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-AEIMYF4P.js";
|
|
18
18
|
import {
|
|
19
19
|
getLogger
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-6MLEBAYZ.js";
|
|
21
21
|
|
|
22
22
|
// src/lib/MergeManager.ts
|
|
23
23
|
var MergeManager = class {
|
|
@@ -369,4 +369,4 @@ To recover:
|
|
|
369
369
|
export {
|
|
370
370
|
MergeManager
|
|
371
371
|
};
|
|
372
|
-
//# sourceMappingURL=chunk-
|
|
372
|
+
//# sourceMappingURL=chunk-XNNXAAZT.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
extractIssueNumber,
|
|
4
4
|
extractPRNumber
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-53OMUNUN.js";
|
|
6
6
|
|
|
7
7
|
// src/utils/IdentifierParser.ts
|
|
8
8
|
var IdentifierParser = class {
|
|
@@ -85,4 +85,4 @@ var IdentifierParser = class {
|
|
|
85
85
|
export {
|
|
86
86
|
IdentifierParser
|
|
87
87
|
};
|
|
88
|
-
//# sourceMappingURL=chunk-
|
|
88
|
+
//# sourceMappingURL=chunk-YU5HVI6B.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
installDependencies,
|
|
4
4
|
runScript
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-LVLRMP7V.js";
|
|
6
6
|
import {
|
|
7
7
|
calculatePortForBranch
|
|
8
8
|
} from "./chunk-VU3QMIP2.js";
|
|
@@ -23,13 +23,13 @@ import {
|
|
|
23
23
|
hasUncommittedChanges,
|
|
24
24
|
isBranchMergedIntoMain,
|
|
25
25
|
isFileTrackedByGit
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-53OMUNUN.js";
|
|
27
27
|
import {
|
|
28
28
|
SettingsManager
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-IDUICCZY.js";
|
|
30
30
|
import {
|
|
31
31
|
MetadataManager
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-CFUWQHCJ.js";
|
|
33
33
|
import {
|
|
34
34
|
calculateForegroundColor,
|
|
35
35
|
generateColorFromBranchName,
|
|
@@ -37,25 +37,24 @@ import {
|
|
|
37
37
|
lightenColor,
|
|
38
38
|
rgbToHex,
|
|
39
39
|
selectDistinctColor
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-433MOLAU.js";
|
|
41
41
|
import {
|
|
42
42
|
generateDeterministicSessionId
|
|
43
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-AEIMYF4P.js";
|
|
44
44
|
import {
|
|
45
|
+
getLogger
|
|
46
|
+
} from "./chunk-6MLEBAYZ.js";
|
|
47
|
+
import {
|
|
48
|
+
detectDarkMode,
|
|
45
49
|
findEnvFileForDatabaseUrl,
|
|
46
50
|
formatEnvLine,
|
|
47
51
|
hasVariableInAnyEnvFile,
|
|
48
52
|
isNoEnvFilesFoundError,
|
|
49
53
|
loadEnvIntoProcess,
|
|
54
|
+
logger,
|
|
50
55
|
parseEnvFile,
|
|
51
56
|
validateEnvVariable
|
|
52
|
-
} from "./chunk-
|
|
53
|
-
import {
|
|
54
|
-
getLogger
|
|
55
|
-
} from "./chunk-6UIGZD2N.js";
|
|
56
|
-
import {
|
|
57
|
-
logger
|
|
58
|
-
} from "./chunk-UYVWLISQ.js";
|
|
57
|
+
} from "./chunk-VT4PDUYT.js";
|
|
59
58
|
|
|
60
59
|
// src/lib/LoomManager.ts
|
|
61
60
|
import path2 from "path";
|
|
@@ -325,7 +324,7 @@ var LoomManager = class {
|
|
|
325
324
|
);
|
|
326
325
|
}
|
|
327
326
|
getLogger().info("Creating placeholder commit for draft PR...");
|
|
328
|
-
const { executeGitCommand: executeGitCommand2, PLACEHOLDER_COMMIT_PREFIX, pushBranchToRemote } = await import("./git-
|
|
327
|
+
const { executeGitCommand: executeGitCommand2, PLACEHOLDER_COMMIT_PREFIX, pushBranchToRemote } = await import("./git-OV6ADVO7.js");
|
|
329
328
|
await executeGitCommand2(
|
|
330
329
|
[
|
|
331
330
|
"commit",
|
|
@@ -339,7 +338,7 @@ var LoomManager = class {
|
|
|
339
338
|
getLogger().debug("Placeholder commit created");
|
|
340
339
|
getLogger().info("Pushing branch to remote for draft PR...");
|
|
341
340
|
await pushBranchToRemote(branchName, worktreePath, { dryRun: false });
|
|
342
|
-
const { PRManager } = await import("./PRManager-
|
|
341
|
+
const { PRManager } = await import("./PRManager-OCSB2HPT.js");
|
|
343
342
|
const prManager = new PRManager(settingsData);
|
|
344
343
|
const prTitle = (issueData == null ? void 0 : issueData.title) ?? `Work on ${branchName}`;
|
|
345
344
|
const prBody = `Draft PR for issue #${input.identifier}
|
|
@@ -360,7 +359,8 @@ This PR was created automatically by iloom.`;
|
|
|
360
359
|
}
|
|
361
360
|
const allMetadata = await this.metadataManager.listAllMetadata();
|
|
362
361
|
const usedHexColors = allMetadata.filter((metadata) => metadata.colorHex !== null).map((metadata) => metadata.colorHex);
|
|
363
|
-
const
|
|
362
|
+
const themeMode = await detectDarkMode();
|
|
363
|
+
const colorData = selectDistinctColor(branchName, usedHexColors, themeMode);
|
|
364
364
|
getLogger().debug(`Selected color ${colorData.hex} for branch ${branchName} (${usedHexColors.length} colors in use globally)`);
|
|
365
365
|
try {
|
|
366
366
|
await this.applyColorSynchronization(worktreePath, branchName, colorData, settingsData, input.options);
|
|
@@ -391,8 +391,8 @@ This PR was created automatically by iloom.`;
|
|
|
391
391
|
const setArguments = (_j = input.options) == null ? void 0 : _j.setArguments;
|
|
392
392
|
const executablePath = (_k = input.options) == null ? void 0 : _k.executablePath;
|
|
393
393
|
if (enableClaude || enableCode || enableDevServer || enableTerminal) {
|
|
394
|
-
const { LoomLauncher } = await import("./LoomLauncher-
|
|
395
|
-
const { ClaudeContextManager } = await import("./ClaudeContextManager-
|
|
394
|
+
const { LoomLauncher } = await import("./LoomLauncher-ZHDTPKED.js");
|
|
395
|
+
const { ClaudeContextManager } = await import("./ClaudeContextManager-PQ46VILL.js");
|
|
396
396
|
const claudeContext = new ClaudeContextManager(void 0, void 0, this.settings);
|
|
397
397
|
const launcher = new LoomLauncher(claudeContext, this.settings);
|
|
398
398
|
await launcher.launchLoom({
|
|
@@ -538,7 +538,7 @@ This PR was created automatically by iloom.`;
|
|
|
538
538
|
async checkAndWarnChildLooms(branchName) {
|
|
539
539
|
let targetBranch = branchName;
|
|
540
540
|
if (!targetBranch) {
|
|
541
|
-
const { getCurrentBranch } = await import("./git-
|
|
541
|
+
const { getCurrentBranch } = await import("./git-OV6ADVO7.js");
|
|
542
542
|
targetBranch = await getCurrentBranch();
|
|
543
543
|
}
|
|
544
544
|
if (!targetBranch) {
|
|
@@ -928,9 +928,10 @@ This PR was created automatically by iloom.`;
|
|
|
928
928
|
colorHex = existingMetadata.colorHex;
|
|
929
929
|
getLogger().debug(`Reusing stored color ${colorHex} for branch ${branchName}`);
|
|
930
930
|
} else {
|
|
931
|
-
const
|
|
931
|
+
const themeMode = await detectDarkMode();
|
|
932
|
+
const colorData = generateColorFromBranchName(branchName, themeMode);
|
|
932
933
|
colorHex = colorData.hex;
|
|
933
|
-
getLogger().debug(`No stored color, using hash-based color ${colorHex} for branch ${branchName}`);
|
|
934
|
+
getLogger().debug(`No stored color, using hash-based color ${colorHex} for branch ${branchName} (${themeMode} mode)`);
|
|
934
935
|
}
|
|
935
936
|
try {
|
|
936
937
|
const colorData = { hex: colorHex, rgb: hexToRgb(colorHex), index: 0 };
|
|
@@ -963,8 +964,8 @@ This PR was created automatically by iloom.`;
|
|
|
963
964
|
const executablePath = (_i = input.options) == null ? void 0 : _i.executablePath;
|
|
964
965
|
if (enableClaude || enableCode || enableDevServer || enableTerminal) {
|
|
965
966
|
getLogger().info("Launching workspace components...");
|
|
966
|
-
const { LoomLauncher } = await import("./LoomLauncher-
|
|
967
|
-
const { ClaudeContextManager } = await import("./ClaudeContextManager-
|
|
967
|
+
const { LoomLauncher } = await import("./LoomLauncher-ZHDTPKED.js");
|
|
968
|
+
const { ClaudeContextManager } = await import("./ClaudeContextManager-PQ46VILL.js");
|
|
968
969
|
const claudeContext = new ClaudeContextManager(void 0, void 0, this.settings);
|
|
969
970
|
const launcher = new LoomLauncher(claudeContext, this.settings);
|
|
970
971
|
await launcher.launchLoom({
|
|
@@ -2370,4 +2371,4 @@ export {
|
|
|
2370
2371
|
DatabaseManager,
|
|
2371
2372
|
ResourceCleanup
|
|
2372
2373
|
};
|
|
2373
|
-
//# sourceMappingURL=chunk-
|
|
2374
|
+
//# sourceMappingURL=chunk-Z5BM4JWB.js.map
|