From 6791069bcace47abeaee7e795d6e55b6dcc5a9d4 Mon Sep 17 00:00:00 2001 From: Glucksberg <80581902+Glucksberg@users.noreply.github.com> Date: Wed, 28 Jan 2026 14:47:29 -0400 Subject: [PATCH] fix: isolate observer sessions to prevent polluting claude --resume list (#837) Observer sessions created by claude-mem were appearing in the main Claude Code session picker (`claude --resume`), cluttering the list with internal plugin sessions that users never intend to resume. In one user's case: 74 observer sessions out of ~220 total (34% noise). ## Solution Set `CLAUDE_CONFIG_DIR` to `~/.claude-mem/observer-config/` when spawning observer Claude processes. This stores observer session files in a separate location, isolating them from user sessions. ## Changes 1. Added `OBSERVER_CONFIG_DIR` to paths.ts 2. Modified `createPidCapturingSpawn()` in ProcessRegistry.ts to inject `CLAUDE_CONFIG_DIR` environment variable Observer sessions now write their `.jsonl` files to: `~/.claude-mem/observer-config/projects/*/` Instead of the user's: `~/.claude/projects/*/` Fixes #832 Co-authored-by: Claude Opus 4.5 --- src/services/worker/ProcessRegistry.ts | 16 +++++++++++++++- src/shared/paths.ts | 4 ++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/services/worker/ProcessRegistry.ts b/src/services/worker/ProcessRegistry.ts index ea09afa6..47c41a0a 100644 --- a/src/services/worker/ProcessRegistry.ts +++ b/src/services/worker/ProcessRegistry.ts @@ -19,6 +19,7 @@ import { spawn, exec, ChildProcess } from 'child_process'; import { promisify } from 'util'; import { logger } from '../../utils/logger.js'; +import { OBSERVER_CONFIG_DIR, ensureDir } from '../../shared/paths.js'; const execAsync = promisify(exec); @@ -187,8 +188,15 @@ export async function reapOrphanedProcesses(activeSessionIds: Set): Prom * * The SDK's spawnClaudeCodeProcess option allows us to intercept subprocess * creation and capture the PID before the SDK hides it. + * + * IMPORTANT (Issue #832): We set CLAUDE_CONFIG_DIR to isolate observer sessions. + * This prevents observer sessions from appearing in `claude --resume` list, + * which was causing 34%+ of resume entries to be internal plugin sessions. */ export function createPidCapturingSpawn(sessionDbId: number) { + // Ensure observer config directory exists + ensureDir(OBSERVER_CONFIG_DIR); + return (spawnOptions: { command: string; args: string[]; @@ -196,9 +204,15 @@ export function createPidCapturingSpawn(sessionDbId: number) { env?: NodeJS.ProcessEnv; signal?: AbortSignal; }) => { + // Inject CLAUDE_CONFIG_DIR to isolate observer sessions (Issue #832) + const isolatedEnv = { + ...spawnOptions.env, + CLAUDE_CONFIG_DIR: OBSERVER_CONFIG_DIR + }; + const child = spawn(spawnOptions.command, spawnOptions.args, { cwd: spawnOptions.cwd, - env: spawnOptions.env, + env: isolatedEnv, stdio: ['pipe', 'pipe', 'pipe'], signal: spawnOptions.signal, // CRITICAL: Pass signal for AbortController integration windowsHide: true diff --git a/src/shared/paths.ts b/src/shared/paths.ts index a4e648a6..75a417cd 100644 --- a/src/shared/paths.ts +++ b/src/shared/paths.ts @@ -38,6 +38,10 @@ export const USER_SETTINGS_PATH = join(DATA_DIR, 'settings.json'); export const DB_PATH = join(DATA_DIR, 'claude-mem.db'); export const VECTOR_DB_DIR = join(DATA_DIR, 'vector-db'); +// Isolated config directory for observer sessions (Issue #832) +// This prevents observer sessions from appearing in `claude --resume` list +export const OBSERVER_CONFIG_DIR = join(DATA_DIR, 'observer-config'); + // Claude integration paths export const CLAUDE_SETTINGS_PATH = join(CLAUDE_CONFIG_DIR, 'settings.json'); export const CLAUDE_COMMANDS_DIR = join(CLAUDE_CONFIG_DIR, 'commands');