@@ -210,22 +210,24 @@ function createEnvDevelopmentLocalFile(
210210 worktreePath : string ,
211211 args : WorktreeArgs ,
212212) : void {
213- // Root .env.development.local - only port overrides that apply globally
214- const rootEnvContent = `# Worktree-specific port overrides
213+ // Root .env.development.local - worktree-specific overrides that apply globally (CLI, web, scripts, etc.)
214+ const rootEnvContent = `# Worktree-specific overrides
215215# Generated by init-worktree.ts for worktree: ${ args . name }
216216# This file has highest precedence in Bun's .env loading order, overriding .env.local
217217PORT=${ args . webPort }
218218NEXT_PUBLIC_WEB_PORT=${ args . webPort }
219+ NEXT_PUBLIC_CODEBUFF_APP_URL=http://localhost:${ args . webPort }
219220`
220221
221222 writeFileSync ( join ( worktreePath , '.env.development.local' ) , rootEnvContent )
222- console . log ( 'Created .env.development.local with port configurations' )
223+ console . log ( 'Created .env.development.local with port and app URL configurations' )
223224
224- // Web-specific .env.development.local - URL override only affects web package
225- // This prevents SDK integration tests from hitting localhost instead of production
225+ // Web-specific .env.development.local - keep an explicit copy for the web package
226+ // The root .env.development.local already ensures the CLI and other packages use the same app URL.
226227 const webEnvContent = `# Web-specific worktree overrides
227228# Generated by init-worktree.ts for worktree: ${ args . name }
228- # This URL override only affects the web package, not SDK tests
229+ # This URL override is duplicated here for clarity; the root .env.development.local
230+ # already sets NEXT_PUBLIC_CODEBUFF_APP_URL for all packages.
229231NEXT_PUBLIC_CODEBUFF_APP_URL=http://localhost:${ args . webPort }
230232`
231233
@@ -247,6 +249,82 @@ function copyInfisicalConfig(worktreePath: string): void {
247249 }
248250}
249251
252+ async function syncInfisicalSecrets ( worktreePath : string ) : Promise < boolean > {
253+ const envLocalPath = join ( worktreePath , '.env.local' )
254+ const infisicalJsonPath = join ( worktreePath , '.infisical.json' )
255+
256+ // Check if .infisical.json exists in worktree
257+ if ( ! existsSync ( infisicalJsonPath ) ) {
258+ console . warn ( 'Skipping Infisical sync: .infisical.json not found in worktree' )
259+ return false
260+ }
261+
262+ console . log ( 'Syncing secrets from Infisical to .env.local...' )
263+
264+ return new Promise ( ( resolve ) => {
265+ const proc = spawn ( 'infisical' , [ 'export' ] , {
266+ cwd : worktreePath ,
267+ stdio : 'pipe' ,
268+ shell : false ,
269+ env : {
270+ ...process . env ,
271+ INFISICAL_DISABLE_UPDATE_CHECK : 'true' ,
272+ } ,
273+ } )
274+
275+ let stdout = ''
276+ let stderr = ''
277+
278+ proc . stdout ?. on ( 'data' , ( data ) => {
279+ stdout += data . toString ( )
280+ } )
281+
282+ proc . stderr ?. on ( 'data' , ( data ) => {
283+ stderr += data . toString ( )
284+ } )
285+
286+ // 10 second timeout
287+ const timeout = setTimeout ( ( ) => {
288+ proc . kill ( )
289+ console . warn ( 'Warning: Infisical sync timed out after 10 seconds' )
290+ console . warn ( 'You may need to run `infisical login` and try again' )
291+ resolve ( false )
292+ } , 10000 )
293+
294+ proc . on ( 'close' , ( code ) => {
295+ clearTimeout ( timeout )
296+
297+ if ( code === 0 && stdout . length > 0 ) {
298+ writeFileSync ( envLocalPath , stdout )
299+ console . log ( 'Synced secrets from Infisical to .env.local' )
300+ resolve ( true )
301+ } else {
302+ if ( stderr . includes ( 'Select the environment' ) || stderr . includes ( 'not logged in' ) ) {
303+ console . warn ( 'Warning: Infisical session expired or not logged in' )
304+ console . warn ( 'Please run `infisical login` in the worktree' )
305+ } else if ( code !== 0 ) {
306+ console . warn ( `Warning: Infisical sync failed (exit code ${ code } )` )
307+ if ( stderr ) {
308+ console . warn ( ` ${ stderr . trim ( ) } ` )
309+ }
310+ }
311+ resolve ( false )
312+ }
313+ } )
314+
315+ proc . on ( 'error' , ( error ) => {
316+ clearTimeout ( timeout )
317+ if ( ( error as NodeJS . ErrnoException ) . code === 'ENOENT' ) {
318+ console . warn ( 'Warning: infisical CLI not found, skipping secret sync' )
319+ console . warn ( 'Install it with: brew install infisical/get-cli/infisical' )
320+ } else {
321+ console . warn ( `Warning: Failed to run infisical: ${ error . message } ` )
322+ }
323+ resolve ( false )
324+ } )
325+ } )
326+ }
327+
250328// Wrapper script no longer needed - .bin/bun handles .env.worktree loading
251329// function createWrapperScript(worktreePath: string): void {
252330// // This function is deprecated - the .bin/bun wrapper now handles .env.worktree loading
@@ -324,7 +402,10 @@ async function main(): Promise<void> {
324402 // Create configuration files
325403 createEnvDevelopmentLocalFile ( worktreePath , args )
326404 copyInfisicalConfig ( worktreePath )
327- // Note: Bun loads .env.development.local with highest precedence, overriding .env.local
405+
406+ // Sync secrets from Infisical to .env.local before running bun install
407+ // This ensures the .bin/bun wrapper doesn't complain about missing .env.local
408+ await syncInfisicalSecrets ( worktreePath )
328409
329410 // Run direnv allow
330411 await runDirenvAllow ( worktreePath )
@@ -333,18 +414,14 @@ async function main(): Promise<void> {
333414 console . log ( 'Installing dependencies with bun...' )
334415 await runCommand ( 'bun' , [ 'install' ] , worktreePath )
335416
336- // Build web directory
337- console . log ( 'Building web directory...' )
338- await runCommand ( 'bun' , [ 'run' , '--cwd' , 'web' , 'build' ] , worktreePath )
339-
340- // Run typecheck
341- console . log ( 'Running typecheck...' )
342- await runCommand ( 'bun' , [ 'run' , 'typecheck' ] , worktreePath )
343-
344417 console . log ( `✅ Worktree '${ args . name } ' created and set up successfully!` )
345418 console . log ( `📁 Location: ${ worktreePath } ` )
346419 console . log ( `🚀 You can now cd into the worktree and start working:` )
347420 console . log ( ` cd ${ worktreePath } ` )
421+ console . log ( `` )
422+ console . log ( `⚠️ Note: NEXT_PUBLIC_CODEBUFF_APP_URL is set to http://localhost:${ args . webPort } ` )
423+ console . log ( ` The CLI and SDK will hit your local web server.` )
424+ console . log ( ` To run SDK E2E tests, start the web server first: bun run --cwd web dev` )
348425 } catch ( error ) {
349426 if ( error instanceof WorktreeError ) {
350427 console . error ( `Error: ${ error . message } ` )
0 commit comments