From 7e9032857c3cb980b2c13e88160ceb7c93e9a28c Mon Sep 17 00:00:00 2001 From: DhanushSantosh Date: Thu, 29 Jan 2026 00:00:44 +0530 Subject: [PATCH 01/20] feat(terminal): Add core infrastructure for custom terminal configurations - Add TerminalConfig types to settings schema (global & project-specific) - Create RC generator with hex-to-xterm-256 color mapping - Create RC file manager for .automaker/terminal/ directory - Add terminal theme color data (40 themes) to platform package - Integrate terminal config injection into TerminalService - Support bash, zsh, and sh with proper env var injection (BASH_ENV, ZDOTDIR, ENV) - Add onThemeChange hook for theme synchronization Part of custom terminal configurations feature implementation. Co-Authored-By: Claude Sonnet 4.5 --- apps/server/src/lib/terminal-themes-data.ts | 25 + apps/server/src/services/terminal-service.ts | 149 ++++- apps/ui/src/config/terminal-themes.d.ts | 66 +++ apps/ui/src/config/terminal-themes.d.ts.map | 1 + apps/ui/src/config/terminal-themes.js | 566 ++++++++++++++++++ apps/ui/src/config/terminal-themes.js.map | 1 + docs/terminal-custom-configs-plan.md | 572 +++++++++++++++++++ libs/platform/src/index.ts | 34 ++ libs/platform/src/rc-file-manager.ts | 250 ++++++++ libs/platform/src/rc-generator.ts | 423 ++++++++++++++ libs/platform/src/terminal-theme-colors.ts | 468 +++++++++++++++ libs/types/src/settings.ts | 56 +- 12 files changed, 2602 insertions(+), 9 deletions(-) create mode 100644 apps/server/src/lib/terminal-themes-data.ts create mode 100644 apps/ui/src/config/terminal-themes.d.ts create mode 100644 apps/ui/src/config/terminal-themes.d.ts.map create mode 100644 apps/ui/src/config/terminal-themes.js create mode 100644 apps/ui/src/config/terminal-themes.js.map create mode 100644 docs/terminal-custom-configs-plan.md create mode 100644 libs/platform/src/rc-file-manager.ts create mode 100644 libs/platform/src/rc-generator.ts create mode 100644 libs/platform/src/terminal-theme-colors.ts diff --git a/apps/server/src/lib/terminal-themes-data.ts b/apps/server/src/lib/terminal-themes-data.ts new file mode 100644 index 000000000..854bf1a80 --- /dev/null +++ b/apps/server/src/lib/terminal-themes-data.ts @@ -0,0 +1,25 @@ +/** + * Terminal Theme Data - Re-export terminal themes from platform package + * + * This module re-exports terminal theme data for use in the server. + */ + +import { terminalThemeColors, getTerminalThemeColors as getThemeColors } from '@automaker/platform'; +import type { ThemeMode } from '@automaker/types'; +import type { TerminalTheme } from '@automaker/platform'; + +/** + * Get terminal theme colors for a given theme mode + */ +export function getTerminalThemeColors(theme: ThemeMode): TerminalTheme { + return getThemeColors(theme); +} + +/** + * Get all terminal themes + */ +export function getAllTerminalThemes(): Record { + return terminalThemeColors; +} + +export default terminalThemeColors; diff --git a/apps/server/src/services/terminal-service.ts b/apps/server/src/services/terminal-service.ts index f83aaede6..836ddabdd 100644 --- a/apps/server/src/services/terminal-service.ts +++ b/apps/server/src/services/terminal-service.ts @@ -13,6 +13,14 @@ import * as path from 'path'; // to enforce ALLOWED_ROOT_DIRECTORY security boundary import * as secureFs from '../lib/secure-fs.js'; import { createLogger } from '@automaker/utils'; +import type { SettingsService } from './settings-service.js'; +import { getTerminalThemeColors, getAllTerminalThemes } from '../lib/terminal-themes-data.js'; +import { + getRcFilePath, + getTerminalDir, + ensureRcFilesUpToDate, + type TerminalConfig, +} from '@automaker/platform'; const logger = createLogger('Terminal'); // System paths module handles shell binary checks and WSL detection @@ -77,6 +85,12 @@ export class TerminalService extends EventEmitter { !!(process.versions && (process.versions as Record).electron) || !!process.env.ELECTRON_RUN_AS_NODE; private useConptyFallback = false; // Track if we need to use winpty fallback on Windows + private settingsService: SettingsService | null = null; + + constructor(settingsService?: SettingsService) { + super(); + this.settingsService = settingsService || null; + } /** * Kill a PTY process with platform-specific handling. @@ -332,6 +346,90 @@ export class TerminalService extends EventEmitter { } } + // Terminal config injection (custom prompts, themes) + const terminalConfigEnv: Record = {}; + if (this.settingsService) { + try { + const globalSettings = await this.settingsService.getGlobalSettings(); + const projectSettings = options.cwd + ? await this.settingsService.getProjectSettings(options.cwd) + : null; + + // Merge global and project terminal configs + const globalTerminalConfig = globalSettings?.terminalConfig; + const projectTerminalConfig = projectSettings?.terminalConfig; + + // Determine if terminal config is enabled + const enabled = + projectTerminalConfig?.enabled !== undefined + ? projectTerminalConfig.enabled + : globalTerminalConfig?.enabled || false; + + if (enabled && globalTerminalConfig) { + const currentTheme = globalSettings?.theme || 'dark'; + const themeColors = getTerminalThemeColors(currentTheme); + const allThemes = getAllTerminalThemes(); + + // Full config object (global + project overrides) + const effectiveConfig: TerminalConfig = { + enabled: true, + customPrompt: globalTerminalConfig.customPrompt, + promptFormat: globalTerminalConfig.promptFormat, + showGitBranch: globalTerminalConfig.showGitBranch, + showGitStatus: globalTerminalConfig.showGitStatus, + customAliases: + projectTerminalConfig?.customAliases || globalTerminalConfig.customAliases, + customEnvVars: { + ...globalTerminalConfig.customEnvVars, + ...projectTerminalConfig?.customEnvVars, + }, + rcFileVersion: globalTerminalConfig.rcFileVersion, + }; + + // Ensure RC files are up to date + await ensureRcFilesUpToDate( + options.cwd || cwd, + currentTheme, + effectiveConfig, + themeColors, + allThemes + ); + + // Set shell-specific env vars + const shellName = path.basename(shell).toLowerCase(); + + if (shellName.includes('bash')) { + terminalConfigEnv.BASH_ENV = getRcFilePath(options.cwd || cwd, 'bash'); + terminalConfigEnv.AUTOMAKER_CUSTOM_PROMPT = effectiveConfig.customPrompt + ? 'true' + : 'false'; + terminalConfigEnv.AUTOMAKER_THEME = currentTheme; + } else if (shellName.includes('zsh')) { + terminalConfigEnv.ZDOTDIR = getTerminalDir(options.cwd || cwd); + terminalConfigEnv.AUTOMAKER_CUSTOM_PROMPT = effectiveConfig.customPrompt + ? 'true' + : 'false'; + terminalConfigEnv.AUTOMAKER_THEME = currentTheme; + } else if (shellName === 'sh') { + terminalConfigEnv.ENV = getRcFilePath(options.cwd || cwd, 'sh'); + terminalConfigEnv.AUTOMAKER_CUSTOM_PROMPT = effectiveConfig.customPrompt + ? 'true' + : 'false'; + terminalConfigEnv.AUTOMAKER_THEME = currentTheme; + } + + // Add custom env vars from config + Object.assign(terminalConfigEnv, effectiveConfig.customEnvVars); + + logger.info( + `[createSession] Terminal config enabled for session ${id}, shell: ${shellName}` + ); + } + } catch (error) { + logger.warn(`[createSession] Failed to apply terminal config: ${error}`); + } + } + const env: Record = { ...cleanEnv, TERM: 'xterm-256color', @@ -341,6 +439,7 @@ export class TerminalService extends EventEmitter { LANG: process.env.LANG || 'en_US.UTF-8', LC_ALL: process.env.LC_ALL || process.env.LANG || 'en_US.UTF-8', ...options.env, + ...terminalConfigEnv, // Apply terminal config env vars last (highest priority) }; logger.info(`Creating session ${id} with shell: ${shell} in ${cwd}`); @@ -652,6 +751,52 @@ export class TerminalService extends EventEmitter { return () => this.exitCallbacks.delete(callback); } + /** + * Handle theme change - regenerate RC files with new theme colors + */ + async onThemeChange(projectPath: string, newTheme: string): Promise { + if (!this.settingsService) { + logger.warn('[onThemeChange] SettingsService not available'); + return; + } + + try { + const globalSettings = await this.settingsService.getGlobalSettings(); + const terminalConfig = globalSettings?.terminalConfig; + + if (terminalConfig?.enabled) { + const themeColors = getTerminalThemeColors( + newTheme as import('@automaker/types').ThemeMode + ); + const allThemes = getAllTerminalThemes(); + + // Regenerate RC files with new theme + const effectiveConfig: TerminalConfig = { + enabled: true, + customPrompt: terminalConfig.customPrompt, + promptFormat: terminalConfig.promptFormat, + showGitBranch: terminalConfig.showGitBranch, + showGitStatus: terminalConfig.showGitStatus, + customAliases: terminalConfig.customAliases, + customEnvVars: terminalConfig.customEnvVars, + rcFileVersion: terminalConfig.rcFileVersion, + }; + + await ensureRcFilesUpToDate( + projectPath, + newTheme as import('@automaker/types').ThemeMode, + effectiveConfig, + themeColors, + allThemes + ); + + logger.info(`[onThemeChange] Regenerated RC files for theme: ${newTheme}`); + } + } catch (error) { + logger.error(`[onThemeChange] Failed to regenerate RC files: ${error}`); + } + } + /** * Clean up all sessions */ @@ -676,9 +821,9 @@ export class TerminalService extends EventEmitter { // Singleton instance let terminalService: TerminalService | null = null; -export function getTerminalService(): TerminalService { +export function getTerminalService(settingsService?: SettingsService): TerminalService { if (!terminalService) { - terminalService = new TerminalService(); + terminalService = new TerminalService(settingsService); } return terminalService; } diff --git a/apps/ui/src/config/terminal-themes.d.ts b/apps/ui/src/config/terminal-themes.d.ts new file mode 100644 index 000000000..e4a875743 --- /dev/null +++ b/apps/ui/src/config/terminal-themes.d.ts @@ -0,0 +1,66 @@ +/** + * Terminal themes that match the app themes + * Each theme provides colors for xterm.js terminal emulator + */ +import type { ThemeMode } from '@/store/app-store'; +import { type UIFontOption } from '@/config/ui-font-options'; +export interface TerminalTheme { + background: string; + foreground: string; + cursor: string; + cursorAccent: string; + selectionBackground: string; + selectionForeground?: string; + black: string; + red: string; + green: string; + yellow: string; + blue: string; + magenta: string; + cyan: string; + white: string; + brightBlack: string; + brightRed: string; + brightGreen: string; + brightYellow: string; + brightBlue: string; + brightMagenta: string; + brightCyan: string; + brightWhite: string; + searchMatchBackground: string; + searchMatchBorder: string; + searchActiveMatchBackground: string; + searchActiveMatchBorder: string; +} +/** + * Terminal font options for user selection + * + * Uses the same fonts as UI_MONO_FONT_OPTIONS for consistency across the app. + * All fonts listed here are bundled with the app via @fontsource packages + * or are system fonts with appropriate fallbacks. + */ +export type TerminalFontOption = UIFontOption; +/** + * Terminal font options - reuses UI_MONO_FONT_OPTIONS with terminal-specific default + * + * The 'default' value means "use the default terminal font" (Menlo/Monaco) + */ +export declare const TERMINAL_FONT_OPTIONS: readonly UIFontOption[]; +/** + * Default terminal font family + * Uses the DEFAULT_FONT_VALUE sentinel which maps to Menlo/Monaco + */ +export declare const DEFAULT_TERMINAL_FONT: any; +/** + * Get the actual font family CSS value for terminal + * Converts DEFAULT_FONT_VALUE to the actual Menlo/Monaco font stack + */ +export declare function getTerminalFontFamily(fontValue: string | undefined): string; +declare const terminalThemes: Record; +/** + * Get terminal theme for the given app theme + * For "system" theme, it checks the user's system preference + */ +export declare function getTerminalTheme(theme: ThemeMode): TerminalTheme; +export default terminalThemes; +//# sourceMappingURL=terminal-themes.d.ts.map diff --git a/apps/ui/src/config/terminal-themes.d.ts.map b/apps/ui/src/config/terminal-themes.d.ts.map new file mode 100644 index 000000000..db9beffe7 --- /dev/null +++ b/apps/ui/src/config/terminal-themes.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"terminal-themes.d.ts","sourceRoot":"","sources":["terminal-themes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,0BAA0B,CAAC;AAElC,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IAEpB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,2BAA2B,EAAE,MAAM,CAAC;IACpC,uBAAuB,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;GAMG;AAGH,MAAM,MAAM,kBAAkB,GAAG,YAAY,CAAC;AAE9C;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,EAAE,SAAS,YAAY,EAMvD,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,qBAAqB,KAAqB,CAAC;AAExD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAK3E;AAoeD,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,SAAS,EAAE,aAAa,CA6CpD,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,aAAa,CAUhE;AAED,eAAe,cAAc,CAAC"} \ No newline at end of file diff --git a/apps/ui/src/config/terminal-themes.js b/apps/ui/src/config/terminal-themes.js new file mode 100644 index 000000000..a788c2853 --- /dev/null +++ b/apps/ui/src/config/terminal-themes.js @@ -0,0 +1,566 @@ +'use strict'; +/** + * Terminal themes that match the app themes + * Each theme provides colors for xterm.js terminal emulator + */ +Object.defineProperty(exports, '__esModule', { value: true }); +exports.DEFAULT_TERMINAL_FONT = exports.TERMINAL_FONT_OPTIONS = void 0; +exports.getTerminalFontFamily = getTerminalFontFamily; +exports.getTerminalTheme = getTerminalTheme; +const ui_font_options_1 = require('@/config/ui-font-options'); +/** + * Terminal font options - reuses UI_MONO_FONT_OPTIONS with terminal-specific default + * + * The 'default' value means "use the default terminal font" (Menlo/Monaco) + */ +exports.TERMINAL_FONT_OPTIONS = ui_font_options_1.UI_MONO_FONT_OPTIONS.map((option) => { + // Replace the UI default label with terminal-specific default + if (option.value === ui_font_options_1.DEFAULT_FONT_VALUE) { + return { value: option.value, label: 'Default (Menlo / Monaco)' }; + } + return option; +}); +/** + * Default terminal font family + * Uses the DEFAULT_FONT_VALUE sentinel which maps to Menlo/Monaco + */ +exports.DEFAULT_TERMINAL_FONT = ui_font_options_1.DEFAULT_FONT_VALUE; +/** + * Get the actual font family CSS value for terminal + * Converts DEFAULT_FONT_VALUE to the actual Menlo/Monaco font stack + */ +function getTerminalFontFamily(fontValue) { + if (!fontValue || fontValue === ui_font_options_1.DEFAULT_FONT_VALUE) { + return "Menlo, Monaco, 'Courier New', monospace"; + } + return fontValue; +} +// Dark theme (default) +const darkTheme = { + background: '#0a0a0a', + foreground: '#d4d4d4', + cursor: '#d4d4d4', + cursorAccent: '#0a0a0a', + selectionBackground: '#264f78', + black: '#1e1e1e', + red: '#f44747', + green: '#6a9955', + yellow: '#dcdcaa', + blue: '#569cd6', + magenta: '#c586c0', + cyan: '#4ec9b0', + white: '#d4d4d4', + brightBlack: '#808080', + brightRed: '#f44747', + brightGreen: '#6a9955', + brightYellow: '#dcdcaa', + brightBlue: '#569cd6', + brightMagenta: '#c586c0', + brightCyan: '#4ec9b0', + brightWhite: '#ffffff', + // Search colors - bright yellow for visibility on dark background + searchMatchBackground: '#6b5300', + searchMatchBorder: '#e2ac00', + searchActiveMatchBackground: '#ff8c00', + searchActiveMatchBorder: '#ffb74d', +}; +// Light theme +const lightTheme = { + background: '#ffffff', + foreground: '#383a42', + cursor: '#383a42', + cursorAccent: '#ffffff', + selectionBackground: '#add6ff', + black: '#383a42', + red: '#e45649', + green: '#50a14f', + yellow: '#c18401', + blue: '#4078f2', + magenta: '#a626a4', + cyan: '#0184bc', + white: '#fafafa', + brightBlack: '#4f525e', + brightRed: '#e06c75', + brightGreen: '#98c379', + brightYellow: '#e5c07b', + brightBlue: '#61afef', + brightMagenta: '#c678dd', + brightCyan: '#56b6c2', + brightWhite: '#ffffff', + // Search colors - darker for visibility on light background + searchMatchBackground: '#fff3b0', + searchMatchBorder: '#c9a500', + searchActiveMatchBackground: '#ffcc00', + searchActiveMatchBorder: '#996600', +}; +// Retro / Cyberpunk theme - neon green on black +const retroTheme = { + background: '#000000', + foreground: '#39ff14', + cursor: '#39ff14', + cursorAccent: '#000000', + selectionBackground: '#39ff14', + selectionForeground: '#000000', + black: '#000000', + red: '#ff0055', + green: '#39ff14', + yellow: '#ffff00', + blue: '#00ffff', + magenta: '#ff00ff', + cyan: '#00ffff', + white: '#39ff14', + brightBlack: '#555555', + brightRed: '#ff5555', + brightGreen: '#55ff55', + brightYellow: '#ffff55', + brightBlue: '#55ffff', + brightMagenta: '#ff55ff', + brightCyan: '#55ffff', + brightWhite: '#ffffff', + // Search colors - magenta/pink for contrast with green text + searchMatchBackground: '#660066', + searchMatchBorder: '#ff00ff', + searchActiveMatchBackground: '#cc00cc', + searchActiveMatchBorder: '#ff66ff', +}; +// Dracula theme +const draculaTheme = { + background: '#282a36', + foreground: '#f8f8f2', + cursor: '#f8f8f2', + cursorAccent: '#282a36', + selectionBackground: '#44475a', + black: '#21222c', + red: '#ff5555', + green: '#50fa7b', + yellow: '#f1fa8c', + blue: '#bd93f9', + magenta: '#ff79c6', + cyan: '#8be9fd', + white: '#f8f8f2', + brightBlack: '#6272a4', + brightRed: '#ff6e6e', + brightGreen: '#69ff94', + brightYellow: '#ffffa5', + brightBlue: '#d6acff', + brightMagenta: '#ff92df', + brightCyan: '#a4ffff', + brightWhite: '#ffffff', + // Search colors - orange for visibility + searchMatchBackground: '#8b5a00', + searchMatchBorder: '#ffb86c', + searchActiveMatchBackground: '#ff9500', + searchActiveMatchBorder: '#ffcc80', +}; +// Nord theme +const nordTheme = { + background: '#2e3440', + foreground: '#d8dee9', + cursor: '#d8dee9', + cursorAccent: '#2e3440', + selectionBackground: '#434c5e', + black: '#3b4252', + red: '#bf616a', + green: '#a3be8c', + yellow: '#ebcb8b', + blue: '#81a1c1', + magenta: '#b48ead', + cyan: '#88c0d0', + white: '#e5e9f0', + brightBlack: '#4c566a', + brightRed: '#bf616a', + brightGreen: '#a3be8c', + brightYellow: '#ebcb8b', + brightBlue: '#81a1c1', + brightMagenta: '#b48ead', + brightCyan: '#8fbcbb', + brightWhite: '#eceff4', + // Search colors - warm yellow/orange for cold blue theme + searchMatchBackground: '#5e4a00', + searchMatchBorder: '#ebcb8b', + searchActiveMatchBackground: '#d08770', + searchActiveMatchBorder: '#e8a87a', +}; +// Monokai theme +const monokaiTheme = { + background: '#272822', + foreground: '#f8f8f2', + cursor: '#f8f8f2', + cursorAccent: '#272822', + selectionBackground: '#49483e', + black: '#272822', + red: '#f92672', + green: '#a6e22e', + yellow: '#f4bf75', + blue: '#66d9ef', + magenta: '#ae81ff', + cyan: '#a1efe4', + white: '#f8f8f2', + brightBlack: '#75715e', + brightRed: '#f92672', + brightGreen: '#a6e22e', + brightYellow: '#f4bf75', + brightBlue: '#66d9ef', + brightMagenta: '#ae81ff', + brightCyan: '#a1efe4', + brightWhite: '#f9f8f5', + // Search colors - orange/gold for contrast + searchMatchBackground: '#6b4400', + searchMatchBorder: '#f4bf75', + searchActiveMatchBackground: '#e69500', + searchActiveMatchBorder: '#ffd080', +}; +// Tokyo Night theme +const tokyonightTheme = { + background: '#1a1b26', + foreground: '#a9b1d6', + cursor: '#c0caf5', + cursorAccent: '#1a1b26', + selectionBackground: '#33467c', + black: '#15161e', + red: '#f7768e', + green: '#9ece6a', + yellow: '#e0af68', + blue: '#7aa2f7', + magenta: '#bb9af7', + cyan: '#7dcfff', + white: '#a9b1d6', + brightBlack: '#414868', + brightRed: '#f7768e', + brightGreen: '#9ece6a', + brightYellow: '#e0af68', + brightBlue: '#7aa2f7', + brightMagenta: '#bb9af7', + brightCyan: '#7dcfff', + brightWhite: '#c0caf5', + // Search colors - warm orange for cold blue theme + searchMatchBackground: '#5c4a00', + searchMatchBorder: '#e0af68', + searchActiveMatchBackground: '#ff9e64', + searchActiveMatchBorder: '#ffb380', +}; +// Solarized Dark theme (improved contrast for WCAG compliance) +const solarizedTheme = { + background: '#002b36', + foreground: '#93a1a1', // Changed from #839496 (base0) to #93a1a1 (base1) for better contrast + cursor: '#93a1a1', + cursorAccent: '#002b36', + selectionBackground: '#073642', + black: '#073642', + red: '#dc322f', + green: '#859900', + yellow: '#b58900', + blue: '#268bd2', + magenta: '#d33682', + cyan: '#2aa198', + white: '#eee8d5', + brightBlack: '#002b36', + brightRed: '#cb4b16', + brightGreen: '#586e75', + brightYellow: '#657b83', + brightBlue: '#839496', + brightMagenta: '#6c71c4', + brightCyan: '#93a1a1', + brightWhite: '#fdf6e3', + // Search colors - orange (solarized orange) for visibility + searchMatchBackground: '#5c3d00', + searchMatchBorder: '#b58900', + searchActiveMatchBackground: '#cb4b16', + searchActiveMatchBorder: '#e07040', +}; +// Gruvbox Dark theme +const gruvboxTheme = { + background: '#282828', + foreground: '#ebdbb2', + cursor: '#ebdbb2', + cursorAccent: '#282828', + selectionBackground: '#504945', + black: '#282828', + red: '#cc241d', + green: '#98971a', + yellow: '#d79921', + blue: '#458588', + magenta: '#b16286', + cyan: '#689d6a', + white: '#a89984', + brightBlack: '#928374', + brightRed: '#fb4934', + brightGreen: '#b8bb26', + brightYellow: '#fabd2f', + brightBlue: '#83a598', + brightMagenta: '#d3869b', + brightCyan: '#8ec07c', + brightWhite: '#ebdbb2', + // Search colors - bright orange for gruvbox + searchMatchBackground: '#6b4500', + searchMatchBorder: '#d79921', + searchActiveMatchBackground: '#fe8019', + searchActiveMatchBorder: '#ffaa40', +}; +// Catppuccin Mocha theme +const catppuccinTheme = { + background: '#1e1e2e', + foreground: '#cdd6f4', + cursor: '#f5e0dc', + cursorAccent: '#1e1e2e', + selectionBackground: '#45475a', + black: '#45475a', + red: '#f38ba8', + green: '#a6e3a1', + yellow: '#f9e2af', + blue: '#89b4fa', + magenta: '#cba6f7', + cyan: '#94e2d5', + white: '#bac2de', + brightBlack: '#585b70', + brightRed: '#f38ba8', + brightGreen: '#a6e3a1', + brightYellow: '#f9e2af', + brightBlue: '#89b4fa', + brightMagenta: '#cba6f7', + brightCyan: '#94e2d5', + brightWhite: '#a6adc8', + // Search colors - peach/orange from catppuccin palette + searchMatchBackground: '#5c4020', + searchMatchBorder: '#fab387', + searchActiveMatchBackground: '#fab387', + searchActiveMatchBorder: '#fcc8a0', +}; +// One Dark theme +const onedarkTheme = { + background: '#282c34', + foreground: '#abb2bf', + cursor: '#528bff', + cursorAccent: '#282c34', + selectionBackground: '#3e4451', + black: '#282c34', + red: '#e06c75', + green: '#98c379', + yellow: '#e5c07b', + blue: '#61afef', + magenta: '#c678dd', + cyan: '#56b6c2', + white: '#abb2bf', + brightBlack: '#5c6370', + brightRed: '#e06c75', + brightGreen: '#98c379', + brightYellow: '#e5c07b', + brightBlue: '#61afef', + brightMagenta: '#c678dd', + brightCyan: '#56b6c2', + brightWhite: '#ffffff', + // Search colors - orange/gold for visibility + searchMatchBackground: '#5c4500', + searchMatchBorder: '#e5c07b', + searchActiveMatchBackground: '#d19a66', + searchActiveMatchBorder: '#e8b888', +}; +// Synthwave '84 theme +const synthwaveTheme = { + background: '#262335', + foreground: '#ffffff', + cursor: '#ff7edb', + cursorAccent: '#262335', + selectionBackground: '#463465', + black: '#262335', + red: '#fe4450', + green: '#72f1b8', + yellow: '#fede5d', + blue: '#03edf9', + magenta: '#ff7edb', + cyan: '#03edf9', + white: '#ffffff', + brightBlack: '#614d85', + brightRed: '#fe4450', + brightGreen: '#72f1b8', + brightYellow: '#f97e72', + brightBlue: '#03edf9', + brightMagenta: '#ff7edb', + brightCyan: '#03edf9', + brightWhite: '#ffffff', + // Search colors - hot pink/magenta for synthwave aesthetic + searchMatchBackground: '#6b2a7a', + searchMatchBorder: '#ff7edb', + searchActiveMatchBackground: '#ff7edb', + searchActiveMatchBorder: '#ffffff', +}; +// Red theme - Dark theme with red accents +const redTheme = { + background: '#1a0a0a', + foreground: '#c8b0b0', + cursor: '#ff4444', + cursorAccent: '#1a0a0a', + selectionBackground: '#5a2020', + black: '#2a1010', + red: '#ff4444', + green: '#6a9a6a', + yellow: '#ccaa55', + blue: '#6688aa', + magenta: '#aa5588', + cyan: '#558888', + white: '#b0a0a0', + brightBlack: '#6a4040', + brightRed: '#ff6666', + brightGreen: '#88bb88', + brightYellow: '#ddbb66', + brightBlue: '#88aacc', + brightMagenta: '#cc77aa', + brightCyan: '#77aaaa', + brightWhite: '#d0c0c0', + // Search colors - orange/gold to contrast with red theme + searchMatchBackground: '#5a3520', + searchMatchBorder: '#ccaa55', + searchActiveMatchBackground: '#ddbb66', + searchActiveMatchBorder: '#ffdd88', +}; +// Cream theme - Warm, soft, easy on the eyes +const creamTheme = { + background: '#f5f3ee', + foreground: '#5a4a3a', + cursor: '#9d6b53', + cursorAccent: '#f5f3ee', + selectionBackground: '#d4c4b0', + black: '#5a4a3a', + red: '#c85a4f', + green: '#7a9a6a', + yellow: '#c9a554', + blue: '#6b8aaa', + magenta: '#a66a8a', + cyan: '#5a9a8a', + white: '#b0a090', + brightBlack: '#8a7a6a', + brightRed: '#e07060', + brightGreen: '#90b080', + brightYellow: '#e0bb70', + brightBlue: '#80a0c0', + brightMagenta: '#c080a0', + brightCyan: '#70b0a0', + brightWhite: '#d0c0b0', + // Search colors - blue for contrast on light cream background + searchMatchBackground: '#c0d4e8', + searchMatchBorder: '#6b8aaa', + searchActiveMatchBackground: '#6b8aaa', + searchActiveMatchBorder: '#4a6a8a', +}; +// Sunset theme - Mellow oranges and soft pastels +const sunsetTheme = { + background: '#1e1a24', + foreground: '#f2e8dd', + cursor: '#dd8855', + cursorAccent: '#1e1a24', + selectionBackground: '#3a2a40', + black: '#1e1a24', + red: '#dd6655', + green: '#88bb77', + yellow: '#ddaa66', + blue: '#6699cc', + magenta: '#cc7799', + cyan: '#66ccaa', + white: '#e8d8c8', + brightBlack: '#4a3a50', + brightRed: '#ee8866', + brightGreen: '#99cc88', + brightYellow: '#eebb77', + brightBlue: '#88aadd', + brightMagenta: '#dd88aa', + brightCyan: '#88ddbb', + brightWhite: '#f5e8dd', + // Search colors - orange for warm sunset theme + searchMatchBackground: '#5a3a30', + searchMatchBorder: '#ddaa66', + searchActiveMatchBackground: '#eebb77', + searchActiveMatchBorder: '#ffdd99', +}; +// Gray theme - Modern, minimal gray scheme inspired by Cursor +const grayTheme = { + background: '#2a2d32', + foreground: '#d0d0d5', + cursor: '#8fa0c0', + cursorAccent: '#2a2d32', + selectionBackground: '#3a3f48', + black: '#2a2d32', + red: '#d87070', + green: '#78b088', + yellow: '#d0b060', + blue: '#7090c0', + magenta: '#a880b0', + cyan: '#60a0b0', + white: '#b0b0b8', + brightBlack: '#606068', + brightRed: '#e88888', + brightGreen: '#90c8a0', + brightYellow: '#e0c878', + brightBlue: '#90b0d8', + brightMagenta: '#c098c8', + brightCyan: '#80b8c8', + brightWhite: '#e0e0e8', + // Search colors - blue for modern feel + searchMatchBackground: '#3a4a60', + searchMatchBorder: '#7090c0', + searchActiveMatchBackground: '#90b0d8', + searchActiveMatchBorder: '#b0d0f0', +}; +// Theme mapping +const terminalThemes = { + // Special + system: darkTheme, // Will be resolved at runtime + // Dark themes + dark: darkTheme, + retro: retroTheme, + dracula: draculaTheme, + nord: nordTheme, + monokai: monokaiTheme, + tokyonight: tokyonightTheme, + solarized: solarizedTheme, + gruvbox: gruvboxTheme, + catppuccin: catppuccinTheme, + onedark: onedarkTheme, + synthwave: synthwaveTheme, + red: redTheme, + sunset: sunsetTheme, + gray: grayTheme, + forest: gruvboxTheme, // Green-ish theme, gruvbox is close + ocean: nordTheme, // Blue-ish theme, nord is close + ember: monokaiTheme, // Warm orange theme, monokai is close + 'ayu-dark': darkTheme, // Deep dark with warm accents + 'ayu-mirage': darkTheme, // Soft dark with golden accents + matcha: nordTheme, // Calming blue-gray with sage green + // Light themes + light: lightTheme, + cream: creamTheme, + solarizedlight: lightTheme, // TODO: Create dedicated solarized light terminal theme + github: lightTheme, // TODO: Create dedicated github terminal theme + paper: lightTheme, + rose: lightTheme, + mint: lightTheme, + lavender: lightTheme, + sand: creamTheme, // Warm tones like cream + sky: lightTheme, + peach: creamTheme, // Warm tones like cream + snow: lightTheme, + sepia: creamTheme, // Warm tones like cream + gruvboxlight: creamTheme, // Warm light theme + nordlight: lightTheme, // Cool light theme + blossom: lightTheme, + 'ayu-light': lightTheme, // Clean light with orange accents + onelight: lightTheme, // Atom One Light - blue accent + bluloco: lightTheme, // Bluloco - cyan-blue accent + feather: lightTheme, // Feather - orange accent +}; +/** + * Get terminal theme for the given app theme + * For "system" theme, it checks the user's system preference + */ +function getTerminalTheme(theme) { + if (theme === 'system') { + // Check system preference + if (typeof window !== 'undefined') { + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + return prefersDark ? darkTheme : lightTheme; + } + return darkTheme; // Default to dark for SSR + } + return terminalThemes[theme] || darkTheme; +} +exports.default = terminalThemes; +//# sourceMappingURL=terminal-themes.js.map diff --git a/apps/ui/src/config/terminal-themes.js.map b/apps/ui/src/config/terminal-themes.js.map new file mode 100644 index 000000000..5c219487c --- /dev/null +++ b/apps/ui/src/config/terminal-themes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"terminal-themes.js","sourceRoot":"","sources":["terminal-themes.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/docs/terminal-custom-configs-plan.md b/docs/terminal-custom-configs-plan.md new file mode 100644 index 000000000..474638e87 --- /dev/null +++ b/docs/terminal-custom-configs-plan.md @@ -0,0 +1,572 @@ +# Implementation Plan: Custom Terminal Configurations with Theme Synchronization + +## Overview + +Implement custom shell configuration files (.bashrc, .zshrc) that automatically sync with Automaker's 40 themes, providing a seamless terminal experience where prompt colors match the app theme. This is an **opt-in feature** that creates configs in `.automaker/terminal/` without modifying user's existing RC files. + +## Architecture + +### Core Components + +1. **RC Generator** (`libs/platform/src/rc-generator.ts`) - NEW + - Template-based generation for bash/zsh/sh + - Theme-to-ANSI color mapping from hex values + - Git info integration (branch, dirty status) + - Prompt format templates (standard, minimal, powerline, starship-inspired) + +2. **RC File Manager** (`libs/platform/src/rc-file-manager.ts`) - NEW + - File I/O for `.automaker/terminal/` directory + - Version checking and regeneration logic + - Path resolution for different shells + +3. **Terminal Service** (`apps/server/src/services/terminal-service.ts`) - MODIFY + - Inject BASH_ENV/ZDOTDIR environment variables when spawning PTY + - Hook for theme change regeneration + - Backwards compatible (no change when disabled) + +4. **Settings Schema** (`libs/types/src/settings.ts`) - MODIFY + - Add `terminalConfig` to GlobalSettings and ProjectSettings + - Include enable toggle, prompt format, git info toggles, custom aliases/env vars + +5. **Settings UI** (`apps/ui/src/components/views/settings-view/terminal/terminal-config-section.tsx`) - NEW + - Enable/disable toggle with explanation + - Prompt format selector (4 formats) + - Git info toggles (branch/status) + - Custom aliases textarea + - Custom env vars key-value editor + - Live preview panel showing example prompt + +## File Structure + +``` +.automaker/terminal/ +├── bashrc.sh # Bash config (sourced via BASH_ENV) +├── zshrc.zsh # Zsh config (via ZDOTDIR) +├── common.sh # Shared functions (git prompt, etc.) +├── themes/ +│ ├── dark.sh # Theme-specific color exports (40 files) +│ ├── dracula.sh +│ ├── nord.sh +│ └── ... (38 more) +├── version.txt # RC file format version (for migrations) +└── user-custom.sh # User's additional customizations (optional) +``` + +## Implementation Steps + +### Step 1: Create RC Generator Package + +**File**: `libs/platform/src/rc-generator.ts` + +**Key Functions**: + +```typescript +// Main generation functions +export function generateBashrc(theme: ThemeMode, config: TerminalConfig): string; +export function generateZshrc(theme: ThemeMode, config: TerminalConfig): string; +export function generateCommonFunctions(): string; +export function generateThemeColors(theme: ThemeMode): string; + +// Color mapping +export function hexToXterm256(hex: string): number; +export function getThemeANSIColors(terminalTheme: TerminalTheme): ANSIColors; +``` + +**Templates**: + +- Source user's original ~/.bashrc or ~/.zshrc first +- Load theme colors from `themes/${AUTOMAKER_THEME}.sh` +- Set custom PS1/PROMPT only if `AUTOMAKER_CUSTOM_PROMPT=true` +- Include git prompt function: `automaker_git_prompt()` + +**Example bashrc.sh template**: + +```bash +#!/bin/bash +# Automaker Terminal Configuration v1.0 + +# Source user's original bashrc first +if [ -f "$HOME/.bashrc" ]; then + source "$HOME/.bashrc" +fi + +# Load Automaker theme colors +AUTOMAKER_THEME="${AUTOMAKER_THEME:-dark}" +if [ -f "${BASH_SOURCE%/*}/themes/$AUTOMAKER_THEME.sh" ]; then + source "${BASH_SOURCE%/*}/themes/$AUTOMAKER_THEME.sh" +fi + +# Load common functions (git prompt) +source "${BASH_SOURCE%/*}/common.sh" + +# Set custom prompt (only if enabled) +if [ "$AUTOMAKER_CUSTOM_PROMPT" = "true" ]; then + PS1="\[$COLOR_USER\]\u@\h\[$COLOR_RESET\] " + PS1="$PS1\[$COLOR_PATH\]\w\[$COLOR_RESET\]" + PS1="$PS1\$(automaker_git_prompt) " + PS1="$PS1\[$COLOR_PROMPT\]\$\[$COLOR_RESET\] " +fi + +# Load user customizations (if exists) +if [ -f "${BASH_SOURCE%/*}/user-custom.sh" ]; then + source "${BASH_SOURCE%/*}/user-custom.sh" +fi +``` + +**Color Mapping Algorithm**: + +1. Get hex colors from `apps/ui/src/config/terminal-themes.ts` (TerminalTheme interface) +2. Convert hex to RGB +3. Map to closest xterm-256 color code using Euclidean distance in RGB space +4. Generate ANSI escape codes: `\[\e[38;5;{code}m\]` for foreground + +### Step 2: Create RC File Manager + +**File**: `libs/platform/src/rc-file-manager.ts` + +**Key Functions**: + +```typescript +export async function ensureTerminalDir(projectPath: string): Promise; +export async function writeRcFiles( + projectPath: string, + theme: ThemeMode, + config: TerminalConfig +): Promise; +export function getRcFilePath(projectPath: string, shell: 'bash' | 'zsh' | 'sh'): string; +export async function checkRcFileVersion(projectPath: string): Promise; +export async function needsRegeneration(projectPath: string, theme: ThemeMode): Promise; +``` + +**File Operations**: + +- Create `.automaker/terminal/` if doesn't exist +- Write RC files with 0644 permissions +- Write theme color files (40 themes × 1 file each) +- Create version.txt with format version (currently "1") +- Support atomic writes (write to temp, then rename) + +### Step 3: Add Settings Schema + +**File**: `libs/types/src/settings.ts` + +**Add to GlobalSettings** (around line 842): + +```typescript +/** Terminal configuration settings */ +terminalConfig?: { + /** Enable custom terminal configurations (default: false) */ + enabled: boolean; + + /** Enable custom prompt (default: true when enabled) */ + customPrompt: boolean; + + /** Prompt format template */ + promptFormat: 'standard' | 'minimal' | 'powerline' | 'starship'; + + /** Show git branch in prompt (default: true) */ + showGitBranch: boolean; + + /** Show git status dirty indicator (default: true) */ + showGitStatus: boolean; + + /** User-provided custom aliases (multiline string) */ + customAliases: string; + + /** User-provided custom env vars */ + customEnvVars: Record; + + /** RC file format version (for migration) */ + rcFileVersion?: number; +}; +``` + +**Add to ProjectSettings**: + +```typescript +/** Project-specific terminal config overrides */ +terminalConfig?: { + /** Override global enabled setting */ + enabled?: boolean; + + /** Project-specific custom aliases */ + customAliases?: string; + + /** Project-specific env vars */ + customEnvVars?: Record; + + /** Custom welcome message for this project */ + welcomeMessage?: string; +}; +``` + +**Defaults**: + +```typescript +const DEFAULT_TERMINAL_CONFIG = { + enabled: false, + customPrompt: true, + promptFormat: 'standard' as const, + showGitBranch: true, + showGitStatus: true, + customAliases: '', + customEnvVars: {}, + rcFileVersion: 1, +}; +``` + +### Step 4: Modify Terminal Service + +**File**: `apps/server/src/services/terminal-service.ts` + +**Modification Point**: In `createSession()` method, around line 335-344 where `env` object is built. + +**Add before PTY spawn**: + +```typescript +// Get terminal config from settings +const terminalConfig = await this.settingsService?.getGlobalSettings(); +const projectSettings = options.projectPath + ? await this.settingsService?.getProjectSettings(options.projectPath) + : null; + +const effectiveTerminalConfig = { + ...terminalConfig?.terminalConfig, + ...projectSettings?.terminalConfig, +}; + +if (effectiveTerminalConfig?.enabled) { + // Ensure RC files are up to date + const currentTheme = terminalConfig?.theme || 'dark'; + await ensureRcFilesUpToDate(options.projectPath || cwd, currentTheme, effectiveTerminalConfig); + + // Set shell-specific env vars + const shellName = path.basename(shell).toLowerCase(); + + if (shellName.includes('bash')) { + env.BASH_ENV = getRcFilePath(options.projectPath || cwd, 'bash'); + env.AUTOMAKER_CUSTOM_PROMPT = effectiveTerminalConfig.customPrompt ? 'true' : 'false'; + env.AUTOMAKER_THEME = currentTheme; + } else if (shellName.includes('zsh')) { + env.ZDOTDIR = path.join(options.projectPath || cwd, '.automaker', 'terminal'); + env.AUTOMAKER_CUSTOM_PROMPT = effectiveTerminalConfig.customPrompt ? 'true' : 'false'; + env.AUTOMAKER_THEME = currentTheme; + } else if (shellName === 'sh') { + env.ENV = getRcFilePath(options.projectPath || cwd, 'sh'); + env.AUTOMAKER_CUSTOM_PROMPT = effectiveTerminalConfig.customPrompt ? 'true' : 'false'; + env.AUTOMAKER_THEME = currentTheme; + } +} +``` + +**Add new method for theme changes**: + +```typescript +async onThemeChange(projectPath: string, newTheme: ThemeMode): Promise { + const globalSettings = await this.settingsService?.getGlobalSettings(); + const terminalConfig = globalSettings?.terminalConfig; + + if (terminalConfig?.enabled) { + // Regenerate RC files with new theme + await writeRcFiles(projectPath, newTheme, terminalConfig); + } +} +``` + +### Step 5: Create Settings UI + +**File**: `apps/ui/src/components/views/settings-view/terminal/terminal-config-section.tsx` + +**Component Structure**: + +```typescript +export function TerminalConfigSection() { + return ( +
+ {/* Enable Toggle with Warning */} +
+ + +

Creates custom shell configs in .automaker/terminal/

+
+ + {enabled && ( + <> + {/* Custom Prompt Toggle */} + + + {/* Prompt Format Selector */} + + + {/* Git Info Toggles */} + + + + {/* Custom Aliases */} +