import { mkdir, writeFile } from 'fs/promises' import * as React from 'react' import type { CommandResultDisplay } from '../../commands.js' import { Dialog } from '@anthropic/ink' import { MemoryFileSelector } from '../../components/memory/MemoryFileSelector.js' import { getRelativeMemoryPath } from '../../components/memory/MemoryUpdateNotification.js' import { Box, Link, Text } from '@anthropic/ink' import type { LocalJSXCommandCall } from '../../types/command.js' import { clearMemoryFileCaches, getMemoryFiles } from '../../utils/claudemd.js' import { getClaudeConfigHomeDir } from '../../utils/envUtils.js' import { getErrnoCode } from '../../utils/errors.js' import { logError } from '../../utils/log.js' import { editFileInEditor } from '../../utils/promptEditor.js' function MemoryCommand({ onDone, }: { onDone: ( result?: string, options?: { display?: CommandResultDisplay }, ) => void }): React.ReactNode { const handleSelectMemoryFile = async (memoryPath: string) => { try { // Create claude directory if it doesn't exist (idempotent with recursive) if (memoryPath.includes(getClaudeConfigHomeDir())) { await mkdir(getClaudeConfigHomeDir(), { recursive: true }) } // Create file if it doesn't exist (wx flag fails if file exists, // which we catch to preserve existing content) try { await writeFile(memoryPath, '', { encoding: 'utf8', flag: 'wx' }) } catch (e: unknown) { if (getErrnoCode(e) !== 'EEXIST') { throw e } } await editFileInEditor(memoryPath) // Determine which environment variable controls the editor let editorSource = 'default' let editorValue = '' if (process.env.VISUAL) { editorSource = '$VISUAL' editorValue = process.env.VISUAL } else if (process.env.EDITOR) { editorSource = '$EDITOR' editorValue = process.env.EDITOR } const editorInfo = editorSource !== 'default' ? `Using ${editorSource}="${editorValue}".` : '' const editorHint = editorInfo ? `> ${editorInfo} To change editor, set $EDITOR or $VISUAL environment variable.` : `> To use a different editor, set the $EDITOR or $VISUAL environment variable.` onDone( `Opened memory file at ${getRelativeMemoryPath(memoryPath)}\n\n${editorHint}`, { display: 'system' }, ) } catch (error) { logError(error) onDone(`Error opening memory file: ${error}`) } } const handleCancel = () => { onDone('Cancelled memory editing', { display: 'system' }) } return ( Learn more: ) } export const call: LocalJSXCommandCall = async onDone => { // Clear + prime before rendering — Suspense handles the unprimed case, // but awaiting here avoids a fallback flash on initial open. clearMemoryFileCaches() await getMemoryFiles() return }