From af69ca719b80d51118a959706d3747ae9e660e42 Mon Sep 17 00:00:00 2001 From: Stefan de Vogelaere Date: Sat, 17 Jan 2026 20:00:35 +0100 Subject: [PATCH] feat(server): add open-in-terminal endpoint Add POST /open-in-terminal endpoint to open a system terminal in the worktree directory using the cross-platform openInTerminal utility. The endpoint validates that worktreePath is provided and is an absolute path for security. Extracted from PR #558. --- apps/server/src/routes/worktree/index.ts | 6 +++ .../worktree/routes/open-in-terminal.ts | 50 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 apps/server/src/routes/worktree/routes/open-in-terminal.ts diff --git a/apps/server/src/routes/worktree/index.ts b/apps/server/src/routes/worktree/index.ts index 4b54ae9e..34850f37 100644 --- a/apps/server/src/routes/worktree/index.ts +++ b/apps/server/src/routes/worktree/index.ts @@ -29,6 +29,7 @@ import { createGetAvailableEditorsHandler, createRefreshEditorsHandler, } from './routes/open-in-editor.js'; +import { createOpenInTerminalHandler } from './routes/open-in-terminal.js'; import { createInitGitHandler } from './routes/init-git.js'; import { createMigrateHandler } from './routes/migrate.js'; import { createStartDevHandler } from './routes/start-dev.js'; @@ -97,6 +98,11 @@ export function createWorktreeRoutes( ); router.post('/switch-branch', requireValidWorktree, createSwitchBranchHandler()); router.post('/open-in-editor', validatePathParams('worktreePath'), createOpenInEditorHandler()); + router.post( + '/open-in-terminal', + validatePathParams('worktreePath'), + createOpenInTerminalHandler() + ); router.get('/default-editor', createGetDefaultEditorHandler()); router.get('/available-editors', createGetAvailableEditorsHandler()); router.post('/refresh-editors', createRefreshEditorsHandler()); diff --git a/apps/server/src/routes/worktree/routes/open-in-terminal.ts b/apps/server/src/routes/worktree/routes/open-in-terminal.ts new file mode 100644 index 00000000..2270ed6f --- /dev/null +++ b/apps/server/src/routes/worktree/routes/open-in-terminal.ts @@ -0,0 +1,50 @@ +/** + * POST /open-in-terminal endpoint - Open a terminal in a worktree directory + * + * This module uses @automaker/platform for cross-platform terminal launching. + */ + +import type { Request, Response } from 'express'; +import { isAbsolute } from 'path'; +import { openInTerminal } from '@automaker/platform'; +import { getErrorMessage, logError } from '../common.js'; + +export function createOpenInTerminalHandler() { + return async (req: Request, res: Response): Promise => { + try { + const { worktreePath } = req.body as { + worktreePath: string; + }; + + if (!worktreePath) { + res.status(400).json({ + success: false, + error: 'worktreePath required', + }); + return; + } + + // Security: Validate that worktreePath is an absolute path + if (!isAbsolute(worktreePath)) { + res.status(400).json({ + success: false, + error: 'worktreePath must be an absolute path', + }); + return; + } + + // Use the platform utility to open in terminal + const result = await openInTerminal(worktreePath); + res.json({ + success: true, + result: { + message: `Opened terminal in ${worktreePath}`, + terminalName: result.terminalName, + }, + }); + } catch (error) { + logError(error, 'Open in terminal failed'); + res.status(500).json({ success: false, error: getErrorMessage(error) }); + } + }; +}