From e0fec4bad71d4d80b7458d6da9d5de7ab9e8f227 Mon Sep 17 00:00:00 2001 From: alan <15989893+adong@users.noreply.github.com> Date: Mon, 23 Feb 2026 20:05:05 -0600 Subject: [PATCH] feat: add terminal output control for SessionStart context (#1143) * feat: add terminal output control for SessionStart context Add CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT setting to control whether context is displayed in the terminal at SessionStart. When set to "false", the terminal remains clean at startup while context is still injected into Claude's system prompt. This allows users who find the context output verbose to disable it without losing the automatic context injection. Defaults to "true" for backward compatibility. Changes: - Add CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT to SettingsDefaultsManager - Check setting in context handler before setting systemMessage - Update settings file format to include new option Co-Authored-By: Claude Sonnet 4.5 * fix: use USER_SETTINGS_PATH and skip color fetch when disabled Address PR feedback from automated review: 1. Use shared USER_SETTINGS_PATH constant instead of hardcoded path - Respects custom CLAUDE_MEM_DATA_DIR override - Consistent with other handlers (session-init, observation) 2. Skip color fetch when terminal output disabled - Check setting before making HTTP requests - Saves network round-trip on every session start Co-Authored-By: Claude Sonnet 4.5 --------- Co-authored-by: Alan Dong Co-authored-by: Claude Sonnet 4.5 --- src/cli/handlers/context.ts | 13 ++++++++++--- src/shared/SettingsDefaultsManager.ts | 2 ++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/cli/handlers/context.ts b/src/cli/handlers/context.ts index a373b8f5..a967a630 100644 --- a/src/cli/handlers/context.ts +++ b/src/cli/handlers/context.ts @@ -10,6 +10,8 @@ import { ensureWorkerRunning, getWorkerPort } from '../../shared/worker-utils.js import { getProjectContext } from '../../utils/project-name.js'; import { HOOK_EXIT_CODES } from '../../shared/hook-constants.js'; import { logger } from '../../utils/logger.js'; +import { SettingsDefaultsManager } from '../../shared/SettingsDefaultsManager.js'; +import { USER_SETTINGS_PATH } from '../../shared/paths.js'; export const contextHandler: EventHandler = { async execute(input: NormalizedHookInput): Promise { @@ -30,6 +32,10 @@ export const contextHandler: EventHandler = { const context = getProjectContext(cwd); const port = getWorkerPort(); + // Check if terminal output should be shown (load settings early) + const settings = SettingsDefaultsManager.loadFromFile(USER_SETTINGS_PATH); + const showTerminalOutput = settings.CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT === 'true'; + // Pass all projects (parent + worktree if applicable) for unified timeline const projectsParam = context.allProjects.join(','); const url = `http://127.0.0.1:${port}/api/context/inject?projects=${encodeURIComponent(projectsParam)}`; @@ -37,11 +43,11 @@ export const contextHandler: EventHandler = { // Note: Removed AbortSignal.timeout due to Windows Bun cleanup issue (libuv assertion) // Worker service has its own timeouts, so client-side timeout is redundant try { - // Fetch both markdown (for Claude context) and colored (for user display) truly in parallel + // Fetch markdown (for Claude context) and optionally colored (for user display) const colorUrl = `${url}&colors=true`; const [response, colorResponse] = await Promise.all([ fetch(url), - fetch(colorUrl).catch(() => null) + showTerminalOutput ? fetch(colorUrl).catch(() => null) : Promise.resolve(null) ]); if (!response.ok) { @@ -60,7 +66,8 @@ export const contextHandler: EventHandler = { const additionalContext = contextResult.trim(); const coloredTimeline = colorResult.trim(); - const systemMessage = coloredTimeline + + const systemMessage = showTerminalOutput && coloredTimeline ? `${coloredTimeline}\n\nView Observations Live @ http://localhost:${port}` : undefined; diff --git a/src/shared/SettingsDefaultsManager.ts b/src/shared/SettingsDefaultsManager.ts index a84ade3e..ba836384 100644 --- a/src/shared/SettingsDefaultsManager.ts +++ b/src/shared/SettingsDefaultsManager.ts @@ -51,6 +51,7 @@ export interface SettingsDefaults { // Feature Toggles CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY: string; CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE: string; + CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT: string; CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED: string; // Process Management CLAUDE_MEM_MAX_CONCURRENT_AGENTS: string; // Max concurrent Claude SDK agent subprocesses (default: 2) @@ -112,6 +113,7 @@ export class SettingsDefaultsManager { // Feature Toggles CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY: 'true', CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE: 'false', + CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT: 'true', CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED: 'false', // Process Management CLAUDE_MEM_MAX_CONCURRENT_AGENTS: '2', // Max concurrent Claude SDK agent subprocesses