# 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, config: TerminalConfig ): 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 "11") - 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'; /** Prompt theme preset */ promptTheme?: TerminalPromptTheme; /** Show git branch in prompt (default: true) */ showGitBranch: boolean; /** Show git status dirty indicator (default: true) */ showGitStatus: boolean; /** Show user and host in prompt (default: true) */ showUserHost: boolean; /** Show path in prompt (default: true) */ showPath: boolean; /** Path display style */ pathStyle: 'full' | 'short' | 'basename'; /** Limit path depth (0 = full path) */ pathDepth: number; /** Show current time in prompt (default: false) */ showTime: boolean; /** Show last command exit status when non-zero (default: false) */ showExitStatus: 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; /** Override prompt theme preset */ promptTheme?: TerminalPromptTheme; /** Override showing user/host */ showUserHost?: boolean; /** Override showing path */ showPath?: boolean; /** Override path style */ pathStyle?: 'full' | 'short' | 'basename'; /** Override path depth (0 = full path) */ pathDepth?: number; /** Override showing time */ showTime?: boolean; /** Override showing exit status */ showExitStatus?: 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, promptTheme: 'custom' as const, showGitBranch: true, showGitStatus: true, showUserHost: true, showPath: true, pathStyle: 'full' as const, pathDepth: 0, showTime: false, showExitStatus: false, customAliases: '', customEnvVars: {}, rcFileVersion: 11, }; ``` **Oh My Posh Themes**: - When `promptTheme` starts with `omp-` and `oh-my-posh` is available, the generated RC files will initialize oh-my-posh with the selected theme name. - If oh-my-posh is not installed, the prompt falls back to the Automaker-built prompt format. - `POSH_THEMES_PATH` is exported to the standard user themes directory so themes resolve offline. ### 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 */}