From f5f2836dce83af6216b3e4bd6008da8516a95a95 Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 14 Mar 2026 00:46:40 +0000 Subject: [PATCH] Add memory usage display showing how many memories were used per response - Add `showMemoryUsage` config option (default: true) to SupermemoryConfig - Instruct the model to display "[Supermemory: N memories loaded]" at the start of each response so users know OpenClaw is using their long-term memory - Add `/memory-usage` slash command to toggle the display on/off at runtime - Include the new option in setup-advanced and status CLI commands https://claude.ai/code/session_01EZwRqj9GjD6K4pqMPRhe2P --- commands/cli.ts | 25 +++++++++++++++++++++++++ commands/slash.ts | 25 +++++++++++++++++++++++++ config.ts | 4 ++++ hooks/recall.ts | 11 ++++++++++- 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/commands/cli.ts b/commands/cli.ts index c38e552..5d8c171 100644 --- a/commands/cli.ts +++ b/commands/cli.ts @@ -190,6 +190,26 @@ export function registerCliSetup(api: OpenClawPluginApi): void { console.log(" Invalid value, using default: all") } + console.log("\nMemory usage display:") + console.log( + " true - Show how many memories were used in each response (recommended)", + ) + console.log( + " false - Hide memory usage counts from responses", + ) + const showMemoryUsageInput = await ask( + "Show memory usage (true/false) [true]: ", + ) + let showMemoryUsage = true + if (showMemoryUsageInput.trim().toLowerCase() === "false") { + showMemoryUsage = false + } else if ( + showMemoryUsageInput.trim() && + showMemoryUsageInput.trim().toLowerCase() !== "true" + ) { + console.log(" Invalid value, using default: true") + } + console.log("\nEntity context:") console.log( " Instructions that guide what memories are extracted from conversations.", @@ -275,6 +295,7 @@ export function registerCliSetup(api: OpenClawPluginApi): void { if (profileFrequency !== 50) pluginConfig.profileFrequency = profileFrequency if (captureMode !== "all") pluginConfig.captureMode = captureMode + if (!showMemoryUsage) pluginConfig.showMemoryUsage = false if (entityContextInput.trim()) pluginConfig.entityContext = entityContextInput.trim() if (enableCustomContainerTags) @@ -311,6 +332,7 @@ export function registerCliSetup(api: OpenClawPluginApi): void { console.log(` Max results: ${maxRecallResults}`) console.log(` Profile freq: ${profileFrequency}`) console.log(` Capture mode: ${captureMode}`) + console.log(` Memory usage: ${showMemoryUsage}`) const entityPreview = entityContextInput.trim() if (entityPreview) { const truncated = @@ -404,6 +426,9 @@ export function registerCliSetup(api: OpenClawPluginApi): void { console.log( ` Capture mode: ${pluginConfig.captureMode ?? "all"}`, ) + console.log( + ` Memory usage: ${pluginConfig.showMemoryUsage ?? true}`, + ) const entityCtx = pluginConfig.entityContext as string | undefined if (entityCtx) { const truncated = diff --git a/commands/slash.ts b/commands/slash.ts index ff7e74f..3750ecc 100644 --- a/commands/slash.ts +++ b/commands/slash.ts @@ -36,6 +36,31 @@ export function registerCommands( cfg: SupermemoryConfig, getSessionKey: () => string | undefined, ): void { + api.registerCommand({ + name: "memory-usage", + description: "Toggle memory usage display on/off", + acceptsArgs: true, + requireAuth: false, + handler: async (ctx: { args?: string }) => { + const arg = ctx.args?.trim().toLowerCase() + + if (arg === "on" || arg === "true" || arg === "enable") { + cfg.showMemoryUsage = true + return { text: "Memory usage display enabled. The model will now show how many memories were used." } + } + + if (arg === "off" || arg === "false" || arg === "disable") { + cfg.showMemoryUsage = false + return { text: "Memory usage display disabled. The model will no longer show memory counts." } + } + + // No arg or unrecognized: toggle + cfg.showMemoryUsage = !cfg.showMemoryUsage + const state = cfg.showMemoryUsage ? "enabled" : "disabled" + return { text: `Memory usage display ${state}. Use /memory-usage on|off to set explicitly.` } + }, + }) + api.registerCommand({ name: "remember", description: "Save something to memory", diff --git a/config.ts b/config.ts index e9d917e..4e4d946 100644 --- a/config.ts +++ b/config.ts @@ -18,6 +18,7 @@ export type SupermemoryConfig = { captureMode: CaptureMode entityContext: string debug: boolean + showMemoryUsage: boolean enableCustomContainerTags: boolean customContainers: CustomContainer[] customContainerInstructions: string @@ -33,6 +34,7 @@ const ALLOWED_KEYS = [ "captureMode", "entityContext", "debug", + "showMemoryUsage", "enableCustomContainerTags", "customContainers", "customContainerInstructions", @@ -125,6 +127,7 @@ export function parseConfig(raw: unknown): SupermemoryConfig { ? cfg.entityContext.trim() : DEFAULT_ENTITY_CONTEXT, debug: (cfg.debug as boolean) ?? false, + showMemoryUsage: (cfg.showMemoryUsage as boolean) ?? true, enableCustomContainerTags: (cfg.enableCustomContainerTags as boolean) ?? false, customContainers, @@ -149,6 +152,7 @@ export const supermemoryConfigSchema = { captureMode: { type: "string", enum: ["all", "everything"] }, entityContext: { type: "string" }, debug: { type: "boolean" }, + showMemoryUsage: { type: "boolean" }, enableCustomContainerTags: { type: "boolean" }, customContainers: { type: "array", diff --git a/hooks/recall.ts b/hooks/recall.ts index 3f0fbc9..5e81621 100644 --- a/hooks/recall.ts +++ b/hooks/recall.ts @@ -68,6 +68,7 @@ function formatContext( dynamicFacts: string[], searchResults: ProfileSearchResult[], maxResults: number, + showMemoryUsage = true, ): string | null { const deduped = deduplicateMemories(staticFacts, dynamicFacts, searchResults) const statics = deduped.static.slice(0, maxResults) @@ -77,6 +78,8 @@ function formatContext( if (statics.length === 0 && dynamics.length === 0 && search.length === 0) return null + const totalMemories = statics.length + dynamics.length + search.length + const sections: string[] = [] if (statics.length > 0) { @@ -111,7 +114,12 @@ function formatContext( const disclaimer = "Do not proactively bring up memories. Only use them when the conversation naturally calls for it." - return `\n${intro}\n\n${sections.join("\n\n")}\n\n${disclaimer}\n` + let memoryUsageInstruction = "" + if (showMemoryUsage) { + memoryUsageInstruction = `\n\nIMPORTANT: At the very beginning of your response, include a brief note indicating how many memories from Supermemory were used to inform your response. Format it as: "[Supermemory: ${totalMemories} memories loaded]" — this helps the user understand that OpenClaw is using their long-term memory. If none of the memories are relevant to the current message, say "[Supermemory: ${totalMemories} memories loaded, 0 used]".` + } + + return `\n${intro}\n\n${sections.join("\n\n")}\n\n${disclaimer}${memoryUsageInstruction}\n` } function countUserTurns(messages: unknown[]): number { @@ -187,6 +195,7 @@ export function buildRecallHandler( includeProfile ? profile.dynamic : [], profile.searchResults, cfg.maxRecallResults, + cfg.showMemoryUsage, ) const containerContext = formatContainerMetadata(cfg, messageProvider)