/** * @license * Copyright 2026 Google LLC * SPDX-License-Identifier: Apache-2.0 */ import { listInboxMemoryPatches, listInboxSkills, listInboxPatches, listMemoryFiles, refreshMemory, showMemory, } from '@google/gemini-cli-core'; import type { Command, CommandContext, CommandExecutionResponse, } from './types.js'; export class MemoryCommand implements Command { readonly name = 'memory'; readonly description = 'Manage memory.'; readonly subCommands = [ new ShowMemoryCommand(), new RefreshMemoryCommand(), new ListMemoryCommand(), new InboxMemoryCommand(), ]; readonly requiresWorkspace = true; async execute( context: CommandContext, _: string[], ): Promise { return new ShowMemoryCommand().execute(context, _); } } export class ShowMemoryCommand implements Command { readonly name = 'memory show'; readonly description = 'Shows the current memory contents.'; async execute( context: CommandContext, _: string[], ): Promise { const result = showMemory(context.agentContext.config); return { name: this.name, data: result.content }; } } export class RefreshMemoryCommand implements Command { readonly name = 'memory refresh'; readonly aliases = ['memory reload']; readonly description = 'Refreshes the memory from the source.'; async execute( context: CommandContext, _: string[], ): Promise { const result = await refreshMemory(context.agentContext.config); return { name: this.name, data: result.content }; } } export class ListMemoryCommand implements Command { readonly name = 'memory list'; readonly description = 'Lists the paths of the GEMINI.md files in use.'; async execute( context: CommandContext, _: string[], ): Promise { const result = listMemoryFiles(context.agentContext.config); return { name: this.name, data: result.content }; } } export class InboxMemoryCommand implements Command { readonly name = 'memory inbox'; readonly description = 'Lists memory items extracted from past sessions that are pending review.'; async execute( context: CommandContext, _: string[], ): Promise { if (!context.agentContext.config.isAutoMemoryEnabled()) { return { name: this.name, data: 'The memory inbox requires Auto Memory. Enable it with: experimental.autoMemory = true in settings.', }; } const [skills, patches, memoryPatches] = await Promise.all([ listInboxSkills(context.agentContext.config), listInboxPatches(context.agentContext.config), listInboxMemoryPatches(context.agentContext.config), ]); if ( skills.length === 0 && patches.length === 0 && memoryPatches.length === 0 ) { return { name: this.name, data: 'No items in inbox.' }; } const lines: string[] = []; for (const s of skills) { const date = s.extractedAt ? ` (extracted: ${new Date(s.extractedAt).toLocaleDateString()})` : ''; lines.push(`- **${s.name}**: ${s.description}${date}`); } for (const p of patches) { const targets = p.entries.map((e) => e.targetPath).join(', '); const date = p.extractedAt ? ` (extracted: ${new Date(p.extractedAt).toLocaleDateString()})` : ''; lines.push(`- **${p.name}** (update): patches ${targets}${date}`); } for (const memoryPatch of memoryPatches) { const targets = memoryPatch.entries.map((e) => e.targetPath).join(', '); const date = memoryPatch.extractedAt ? ` (latest extract: ${new Date(memoryPatch.extractedAt).toLocaleDateString()})` : ''; const sourceCount = memoryPatch.sourceFiles.length; const sourceLabel = sourceCount === 1 ? 'patch' : 'patches'; lines.push( `- **${memoryPatch.name}** (${sourceCount} source ${sourceLabel}, ${memoryPatch.entries.length} hunks): targets ${targets}${date}`, ); } const total = skills.length + patches.length + memoryPatches.length; return { name: this.name, data: `Memory inbox (${total}):\n${lines.join('\n')}`, }; } }