From eb4ce4301b242d013fe0d2d8a0a76f83f2a2edd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Padez?= Date: Fri, 24 Jul 2026 09:43:01 +0000 Subject: [PATCH] chat: run /chat sessions from the dedicated claude_sessions cwd The standalone /chat route now tags its context as 'chat'; the backend runs those sessions with cwd = DATA_PATH//claude_sessions (created on demand), so their transcripts form an isolated Claude project group instead of polluting the home-dir history. Other chat contexts (email/project panels) keep their own cwd. Co-Authored-By: Claude Opus 4.8 --- src/servers/api/chat/claude-sessions.ts | 9 ++++++++- src/servers/api/pi/websocket.ts | 6 +++++- .../officerdev/src/apps/Chat/ChatPanelWrapper.tsx | 12 +++++++----- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/servers/api/chat/claude-sessions.ts b/src/servers/api/chat/claude-sessions.ts index d8f7c672..6e75c240 100644 --- a/src/servers/api/chat/claude-sessions.ts +++ b/src/servers/api/chat/claude-sessions.ts @@ -1,4 +1,4 @@ -import { readdirSync, readFileSync, existsSync, statSync } from 'node:fs'; +import { readdirSync, readFileSync, existsSync, statSync, mkdirSync } from 'node:fs'; import { join } from 'node:path'; import { DATA_PATH } from '../../data-path'; @@ -12,6 +12,13 @@ import { DATA_PATH } from '../../data-path'; /** Dedicated working directory for /chat sessions, so they form their own Claude "project" group. */ export const getClaudeSessionsCwd = (email: string): string => join(DATA_PATH, email, 'claude_sessions'); +/** Same, but create the directory if it doesn't exist (call before spawning a /chat session). */ +export const ensureClaudeSessionsCwd = (email: string): string => { + const dir = getClaudeSessionsCwd(email); + mkdirSync(dir, { recursive: true }); + return dir; +}; + const claudeProjectsDir = (email: string): string => join(DATA_PATH, email, 'home', '.claude', 'projects'); /** Claude's folder name for a working directory. */ diff --git a/src/servers/api/pi/websocket.ts b/src/servers/api/pi/websocket.ts index e43bba04..1e054991 100644 --- a/src/servers/api/pi/websocket.ts +++ b/src/servers/api/pi/websocket.ts @@ -4,6 +4,7 @@ import type { ClientMessage, ServerMessage, Message, PiEvent } from './types'; import { sessionManager } from './session-manager'; import * as storage from './storage'; import { sendClaudeCodeStreaming } from '@@/channels/send-claude-code'; +import { ensureClaudeSessionsCwd } from '../chat/claude-sessions'; import * as sidecar from '@@/sidecar-registry'; import { join } from 'path'; import { getHomeDirForRole } from '../../../servers/data-path'; @@ -296,7 +297,10 @@ async function handleClaudeCodeChat( const { email, username, userId } = ws.data; const homeDir = getHomeDirForRole(email, ws.data.role); - const cwd = resolveCwd(email, ws.data.role, msg.cwd); + // The standalone /chat route runs every session from a dedicated `claude_sessions` working + // directory, so its transcripts form their own Claude "project" group (source of truth) instead of + // polluting the home-dir history. Other contexts (email/project panels) keep their own cwd. + const cwd = msg.context === 'chat' ? ensureClaudeSessionsCwd(email) : resolveCwd(email, ws.data.role, msg.cwd); const groupSlug = msg.groupSlug || null; diff --git a/src/workspaces/officerdev/src/apps/Chat/ChatPanelWrapper.tsx b/src/workspaces/officerdev/src/apps/Chat/ChatPanelWrapper.tsx index 742c5013..40a6f1f7 100644 --- a/src/workspaces/officerdev/src/apps/Chat/ChatPanelWrapper.tsx +++ b/src/workspaces/officerdev/src/apps/Chat/ChatPanelWrapper.tsx @@ -94,11 +94,13 @@ export const ChatPanelWrapper = () => { const chatContext = dashboardId === 'email' || dashboardId === 'screens/email' ? { context: 'email' as const } - : dashboardId?.startsWith('proj-layout-') - ? { context: 'project' as const, contextId: dashboardId.replace('proj-layout-', '') } - : dashboardId && !dashboardId.startsWith('screens/') - ? { context: 'dashboard' as const, contextId: dashboardId } - : {}; + : dashboardId === 'screens/chat' + ? { context: 'chat' as const } + : dashboardId?.startsWith('proj-layout-') + ? { context: 'project' as const, contextId: dashboardId.replace('proj-layout-', '') } + : dashboardId && !dashboardId.startsWith('screens/') + ? { context: 'dashboard' as const, contextId: dashboardId } + : {}; const [savedId, setSavedId] = usePanelChannel('chat:saved-id', null); const [selection, setSelection] = usePanelChannel('chat:panel-session', null);