44 STORAGE_KEY_COLOR ,
55 STORAGE_KEY_SYNC ,
66 STORAGE_KEY_TERM_THEME ,
7+ STORAGE_KEY_TERM_FOLLOW_APP_THEME ,
78 STORAGE_KEY_THEME ,
89 STORAGE_KEY_TERM_FONT_FAMILY ,
910 STORAGE_KEY_TERM_FONT_SIZE ,
@@ -37,6 +38,7 @@ import {
3738} from '../../infrastructure/config/storageKeys' ;
3839import { DEFAULT_UI_LOCALE , resolveSupportedLocale } from '../../infrastructure/config/i18n' ;
3940import { TERMINAL_THEMES } from '../../infrastructure/config/terminalThemes' ;
41+ import { getTerminalThemeForUiTheme } from '../../domain/terminalAppearance' ;
4042import { customThemeStore , useCustomThemes } from '../state/customThemeStore' ;
4143import { DEFAULT_FONT_SIZE } from '../../infrastructure/config/fonts' ;
4244import { DARK_UI_THEMES , LIGHT_UI_THEMES , UiThemeTokens , getUiThemeById } from '../../infrastructure/config/uiThemes' ;
@@ -195,6 +197,17 @@ export const useSettingsState = () => {
195197 } ) ;
196198 const [ syncConfig , setSyncConfig ] = useState < SyncConfig | null > ( ( ) => localStorageAdapter . read < SyncConfig > ( STORAGE_KEY_SYNC ) ) ;
197199 const [ terminalThemeId , setTerminalThemeId ] = useState < string > ( ( ) => localStorageAdapter . readString ( STORAGE_KEY_TERM_THEME ) || DEFAULT_TERMINAL_THEME ) ;
200+ const [ followAppTerminalTheme , setFollowAppTerminalThemeState ] = useState < boolean > ( ( ) => {
201+ const stored = localStorageAdapter . readString ( STORAGE_KEY_TERM_FOLLOW_APP_THEME ) ;
202+ if ( stored !== null ) return stored === 'true' ;
203+ // First time seeing this key. For genuinely fresh installs (no existing
204+ // terminal theme in storage) default ON so the terminal matches the app
205+ // theme out of the box. For upgrades from an older version (existing
206+ // terminal theme present) default OFF to avoid silently overriding the
207+ // user's manual choice.
208+ const isUpgrade = ! ! localStorageAdapter . readString ( STORAGE_KEY_TERM_THEME ) ;
209+ return ! isUpgrade ;
210+ } ) ;
198211 const [ terminalFontFamilyId , setTerminalFontFamilyId ] = useState < string > ( ( ) => localStorageAdapter . readString ( STORAGE_KEY_TERM_FONT_FAMILY ) || DEFAULT_FONT_FAMILY ) ;
199212 const [ terminalFontSize , setTerminalFontSize ] = useState < number > ( ( ) => localStorageAdapter . readNumber ( STORAGE_KEY_TERM_FONT_SIZE ) || DEFAULT_FONT_SIZE ) ;
200213 const [ uiLanguage , setUiLanguage ] = useState < UILanguage > ( ( ) => {
@@ -539,6 +552,10 @@ export const useSettingsState = () => {
539552 if ( key === STORAGE_KEY_TERM_THEME && typeof value === 'string' ) {
540553 setTerminalThemeId ( value ) ;
541554 }
555+ if ( key === STORAGE_KEY_TERM_FOLLOW_APP_THEME ) {
556+ const next = value === true || value === 'true' ;
557+ setFollowAppTerminalThemeState ( ( prev ) => ( prev === next ? prev : next ) ) ;
558+ }
542559 if ( key === STORAGE_KEY_TERM_FONT_FAMILY && typeof value === 'string' ) {
543560 setTerminalFontFamilyId ( value ) ;
544561 }
@@ -642,7 +659,7 @@ export const useSettingsState = () => {
642659 const settingsSnapshotRef = useRef ( {
643660 theme, lightUiThemeId, darkUiThemeId, accentMode, customAccent,
644661 customCSS, uiFontFamilyId, hotkeyScheme, uiLanguage,
645- terminalThemeId, terminalFontFamilyId, terminalFontSize,
662+ terminalThemeId, followAppTerminalTheme , terminalFontFamilyId, terminalFontSize,
646663 sftpDoubleClickBehavior, sftpAutoSync, sftpShowHiddenFiles,
647664 sftpUseCompressedUpload, sftpAutoOpenSidebar, sftpDefaultViewMode,
648665 editorWordWrap, sessionLogsEnabled, sessionLogsDir, sessionLogsFormat,
@@ -651,7 +668,7 @@ export const useSettingsState = () => {
651668 settingsSnapshotRef . current = {
652669 theme, lightUiThemeId, darkUiThemeId, accentMode, customAccent,
653670 customCSS, uiFontFamilyId, hotkeyScheme, uiLanguage,
654- terminalThemeId, terminalFontFamilyId, terminalFontSize,
671+ terminalThemeId, followAppTerminalTheme , terminalFontFamilyId, terminalFontSize,
655672 sftpDoubleClickBehavior, sftpAutoSync, sftpShowHiddenFiles,
656673 sftpUseCompressedUpload, sftpAutoOpenSidebar, sftpDefaultViewMode,
657674 editorWordWrap, sessionLogsEnabled, sessionLogsDir, sessionLogsFormat,
@@ -732,6 +749,13 @@ export const useSettingsState = () => {
732749 setTerminalThemeId ( e . newValue ) ;
733750 }
734751 }
752+ // Sync follow-app-theme toggle from other windows
753+ if ( e . key === STORAGE_KEY_TERM_FOLLOW_APP_THEME && e . newValue ) {
754+ const next = e . newValue === 'true' ;
755+ if ( next !== s . followAppTerminalTheme ) {
756+ setFollowAppTerminalThemeState ( next ) ;
757+ }
758+ }
735759 // Sync terminal font family from other windows
736760 if ( e . key === STORAGE_KEY_TERM_FONT_FAMILY && e . newValue ) {
737761 if ( e . newValue !== s . terminalFontFamilyId ) {
@@ -849,6 +873,12 @@ export const useSettingsState = () => {
849873 notifySettingsChanged ( STORAGE_KEY_TERM_THEME , terminalThemeId ) ;
850874 } , [ terminalThemeId , notifySettingsChanged ] ) ;
851875
876+ useEffect ( ( ) => {
877+ localStorageAdapter . writeString ( STORAGE_KEY_TERM_FOLLOW_APP_THEME , String ( followAppTerminalTheme ) ) ;
878+ if ( ! persistMountedRef . current ) return ;
879+ notifySettingsChanged ( STORAGE_KEY_TERM_FOLLOW_APP_THEME , String ( followAppTerminalTheme ) ) ;
880+ } , [ followAppTerminalTheme , notifySettingsChanged ] ) ;
881+
852882 useEffect ( ( ) => {
853883 localStorageAdapter . writeString ( STORAGE_KEY_TERM_FONT_FAMILY , terminalFontFamilyId ) ;
854884 if ( ! persistMountedRef . current ) return ;
@@ -1116,12 +1146,21 @@ export const useSettingsState = () => {
11161146 // Subscribe to custom theme changes so editing in-place triggers re-render
11171147 const customThemes = useCustomThemes ( ) ;
11181148
1119- const currentTerminalTheme = useMemo (
1120- ( ) => TERMINAL_THEMES . find ( t => t . id === terminalThemeId )
1149+ const currentTerminalTheme = useMemo ( ( ) => {
1150+ // When "Follow Application Theme" is enabled, pick the terminal theme
1151+ // whose background matches the active UI theme preset.
1152+ if ( followAppTerminalTheme ) {
1153+ const activeUiThemeId = resolvedTheme === 'dark' ? darkUiThemeId : lightUiThemeId ;
1154+ const mapped = getTerminalThemeForUiTheme ( activeUiThemeId ) ;
1155+ if ( mapped ) {
1156+ const found = TERMINAL_THEMES . find ( t => t . id === mapped ) ;
1157+ if ( found ) return found ;
1158+ }
1159+ }
1160+ return TERMINAL_THEMES . find ( t => t . id === terminalThemeId )
11211161 || customThemes . find ( t => t . id === terminalThemeId )
1122- || TERMINAL_THEMES [ 0 ] ,
1123- [ terminalThemeId , customThemes ]
1124- ) ;
1162+ || TERMINAL_THEMES [ 0 ] ;
1163+ } , [ terminalThemeId , customThemes , followAppTerminalTheme , resolvedTheme , lightUiThemeId , darkUiThemeId ] ) ;
11251164
11261165 const updateTerminalSetting = useCallback ( < K extends keyof TerminalSettings > (
11271166 key : K ,
@@ -1156,6 +1195,8 @@ export const useSettingsState = () => {
11561195 setUiLanguage,
11571196 terminalThemeId,
11581197 setTerminalThemeId,
1198+ followAppTerminalTheme,
1199+ setFollowAppTerminalTheme : setFollowAppTerminalThemeState ,
11591200 currentTerminalTheme,
11601201 terminalFontFamilyId,
11611202 setTerminalFontFamilyId,
0 commit comments