Skip to main content
Glama

session_export_memory

Export project memory to local files for data portability and archiving. Supports JSON for machine-readable exports and Markdown for human-readable documentation.

Instructions

Export all of a project's memory to a local file. Fulfills GDPR Article 20 (Right to Data Portability) and the 'local-first' portability promise.

What is exported:

  • All session ledger entries (summaries, decisions, TODOs, file changes)

  • Current handoff state (live project context)

  • System settings (API keys are "REDACTED" for security)

  • Visual memory index (descriptions, captions, timestamps; not the raw files)

Formats:

  • json — machine-readable, suitable for import into another Prism instance

  • markdown — human-readable, ideal for Obsidian, Notion, or archiving

⚠️ Output directory must exist and be writable. Filenames are auto-generated: prism-export-<project>-<date>.(json|md)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectNoProject to export. If omitted, exports ALL projects into separate files.
formatNoExport format: 'json' (machine-readable) or 'markdown' (human-readable). Default: json.json
output_dirYesAbsolute path to the directory where the export file(s) will be written. Must exist and be writable. Example: '/Users/admin/Desktop'.

Implementation Reference

  • The handler function `sessionExportMemoryHandler` that executes the `session_export_memory` tool logic. It fetches session data, redacts sensitive settings, and exports the data to a local JSON or Markdown file.
    export async function sessionExportMemoryHandler(args: unknown) {
      if (!isSessionExportMemoryArgs(args)) {
        return {
          content: [{ type: "text", text: "Error: output_dir (string) is required." }],
          isError: true,
        };
      }
    
      const { output_dir, format = "json" } = args;
      const requestedProject = (args as { project?: string }).project;
    
      // Validate output directory
      if (!existsSync(output_dir)) {
        return {
          content: [{
            type: "text",
            text: `Error: output_dir does not exist: "${output_dir}". Please create it first.`,
          }],
          isError: true,
        };
      }
    
      const storage = await getStorage();
      const exportedFiles: string[] = [];
    
      try {
        // Determine which projects to export
        let projects: string[];
        if (requestedProject) {
          projects = [requestedProject];
        } else {
          projects = await storage.listProjects();
          if (projects.length === 0) {
            return {
              content: [{ type: "text", text: "No projects found in memory — nothing to export." }],
              isError: false,
            };
          }
        }
    
        // Fetch settings once (shared across all projects)
        const rawSettings = await getAllSettings();
        const safeSettings = redactSettings(rawSettings);
        const exportedAt = new Date().toISOString();
        const dateSuffix = exportedAt.split("T")[0]; // YYYY-MM-DD
    
        for (const project of projects) {
          debugLog(`[session_export_memory] Exporting project "${project}" as ${format}`);
    
          // Fetch handoff (live context)
          const ctx = await storage.loadContext(project, "deep", PRISM_USER_ID) as {
            metadata?: { visual_memory?: unknown[] };
            [key: string]: unknown;
          } | null;
    
          // Fetch full ledger (all non-deleted entries)
          const ledger = await storage.getLedgerEntries({ project }) as Array<{
            id?: string;
            created_at?: string;
            event_type?: string;
            summary: string;
            todos?: string[];
            decisions?: string[];
            files_changed?: string[];
            embedding?: string | null; // strip from export (large + not human-useful)
            [key: string]: unknown;
          }>;
    
          // Strip raw embedding vectors from the export (large binary data)
          const cleanLedger = ledger.map(({ embedding: _emb, ...rest }) => rest);
    
          const visualMemory = (ctx?.metadata?.visual_memory as unknown[] | undefined) ?? [];
    
          const exportPayload = {
            prism_export: {
              version: "4.5",
              exported_at: exportedAt,
              project,
              settings: safeSettings,
              handoff: ctx ?? null,
              visual_memory: visualMemory,
              ledger: cleanLedger,
            },
          };
    
          // Serialize
          const ext = format === "markdown" ? "md" : "json";
          const filename = `prism-export-${project}-${dateSuffix}.${ext}`;
          const outputPath = join(output_dir, filename);
    
          let content: string;
          if (format === "markdown") {
            content = toMarkdown(exportPayload);
          } else {
            content = JSON.stringify(exportPayload, null, 2);
          }
    
          await writeFile(outputPath, content, "utf-8");
          exportedFiles.push(outputPath);
          debugLog(`[session_export_memory] Wrote ${content.length} bytes to ${outputPath}`);
        }
    
        const plural = exportedFiles.length > 1 ? "files" : "file";
        return {
          content: [{
            type: "text",
            text:
              `✅ Memory exported successfully (${format.toUpperCase()})\n\n` +
              `**Project(s):** ${projects.join(", ")}\n` +
              `**${exportedFiles.length} ${plural} written:**\n` +
              exportedFiles.map(f => `  \u2022 \`${f}\``).join("\n") +
              `\n\n⚠️ API keys have been redacted. Vault image files are NOT included — ` +
              `only metadata and captions. Re-run \`session_save_image\` to re-attach images.`,
          }],
          isError: false,
        };
      } catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        console.error(`[session_export_memory] Error: ${msg}`);
        return {
          content: [{ type: "text", text: `Export failed: ${msg}` }],
          isError: true,
        };
      }
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/dcostenco/BCBA'

If you have feedback or need assistance with the MCP directory API, please join our Discord server