mnemonio

skill
Security Audit
Pass
Health Pass
  • License — License: MIT
  • Description — Repository has a description
  • Active repo — Last push 0 days ago
  • Community trust — 13 GitHub stars
Code Pass
  • Code scan — Scanned 12 files during light audit, no dangerous patterns found
Permissions Pass
  • Permissions — No dangerous permissions requested
Purpose
This tool provides a persistent, file-based memory layer for LLM agents. It saves agent knowledge across sessions using markdown files with YAML frontmatter, and includes features like semantic search and automatic fact extraction.

Security Assessment
Overall risk: Low. The code scan of 12 files found no dangerous patterns, hardcoded secrets, or requests for dangerous permissions. The tool operates primarily on the local file system within a designated directory (`./.mnemonio`). It does make external network requests, but only to user-configured LLM API endpoints (such as OpenAI or Anthropic) required for its search and memory extraction features. Users must intentionally provide their own API keys and base URLs via environment variables. No hidden or malicious execution behaviors were detected.

Quality Assessment
The project is in very active development, with the most recent push occurring just today. It is properly licensed under the standard MIT license. However, as a newer tool, its community footprint is quite small, currently sitting at only 13 GitHub stars. This means it has not yet been widely battle-tested by a large audience, despite passing all automated health checks.

Verdict
Safe to use, provided you are comfortable trusting a relatively new and untested tool with your LLM API keys.
SUMMARY

A persistent file-first memory layer for LLM agents, optimized for developer workflows.

README.md

mnemonio

mnemonio.com

Persistent structured memory layer for LLM agents. Mnemonio gives your agent a
file-based memory system that survives across sessions -- markdown files with
YAML frontmatter, a manifest file, semantic search, automatic extraction from
conversations, and periodic consolidation.

It ships as an MCP server, a CLI, and a TypeScript library. LLM operations use
a callback you provide, so it works with any provider.

MCP Server

The fastest way to get started. Add mnemonio to your MCP client settings and
your AI coding assistant gets persistent memory automatically.

Setup

{
  "mcpServers": {
    "mnemonio": {
      "command": "npx",
      "args": ["-p", "@memel06/mnemonio", "mnemonio-mcp"],
      "env": {
        "MNEMONIO_DIR": "./.mnemonio"
      }
    }
  }
}

For LLM-dependent tools (search, extract, distill), create a .env file in your
project root (and add it to .gitignore):

MNEMONIO_API_KEY=your-api-key
MNEMONIO_BASE_URL=https://your-llm-provider.com/v1
MNEMONIO_MODEL=your-model

Mnemonio loads .env automatically.

You can also pass these as env vars in the MCP config if you prefer:

{
  "mcpServers": {
    "mnemonio": {
      "command": "npx",
      "args": ["-p", "@memel06/mnemonio", "mnemonio-mcp"],
      "env": {
        "MNEMONIO_DIR": "./.mnemonio",
        "MNEMONIO_BASE_URL": "https://your-llm-provider.com/v1",
        "MNEMONIO_MODEL": "your-model"
      }
    }
  }
}

The server auto-detects the provider from the base URL:

Base URL contains Provider Token param Auth Endpoint
openai.com OpenAI (modern) max_completion_tokens Bearer /chat/completions
anthropic.com Anthropic max_tokens x-api-key /v1/messages
openrouter.ai OpenRouter max_tokens Bearer /chat/completions
anything else Generic (OpenAI-compatible) max_tokens Bearer /chat/completions

Override auto-detection with MNEMONIO_PROVIDER (in .env or MCP config):

MNEMONIO_PROVIDER=anthropic
MNEMONIO_API_KEY=sk-ant-...
MNEMONIO_BASE_URL=https://api.anthropic.com
MNEMONIO_MODEL=claude-sonnet-4-6-20250514

Valid provider values: openai, openai-classic, anthropic, openrouter.

Available Tools

Tool LLM needed Team aware Description
memory_list No Yes List all memories, optionally filtered by type or tags
memory_read No Yes Read full content of a memory file
memory_save No No Save a new memory with frontmatter + manifest entry
memory_delete No No Delete a memory file and remove it from the manifest
memory_search Yes Yes Semantic search across all memories, with optional tag pre-filter
memory_extract Yes No Auto-extract durable facts from a conversation
memory_distill Yes No Consolidate: merge duplicates, prune stale, tighten
memory_stats No Yes File count, size, type breakdown

Team Memory

Team memory is a shared, read-only directory that gives every developer's agent
the same baseline context -- coding standards, onboarding notes, project
conventions. Commit it to your repo so the whole team shares it.

MCP Server

Set MNEMONIO_TEAM_DIR in your MCP config:

{
  "mcpServers": {
    "mnemonio": {
      "command": "npx",
      "args": ["-p", "@memel06/mnemonio", "mnemonio-mcp"],
      "env": {
        "MNEMONIO_DIR": "./.mnemonio",
        "MNEMONIO_TEAM_DIR": "./team-memory"
      }
    }
  }
}

Team memories automatically appear in memory_list, memory_read,
memory_search, and memory_stats. Write operations (memory_save,
memory_extract, memory_distill) only touch the private directory.

CLI

Use --team-dir with any read command:

mnemonio list .mnemonio --team-dir ./team-memory
mnemonio search "coding standards" .mnemonio --team-dir ./team-memory

Library

const store = createMnemonioStore({
  memoryDir: './.mnemonio',
  teamDir: './team-memory',
});

// Combined prompt includes both private and team memories
const prompt = await store.buildCombinedPrompt();

// Path traversal protection for team writes
const safePath = await store.validateTeamWritePath('notes.md');

Security

Path traversal attacks (symlinks, ../ segments, null bytes) are blocked by
validateTeamWritePath. Use isTeamPath to check if a path falls within the
team directory.

CLI

npm install -g @memel06/mnemonio

The CLI reads MNEMONIO_API_KEY from your environment for LLM-dependent
commands (search, distill). It auto-detects the provider from
MNEMONIO_BASE_URL (or you can set MNEMONIO_PROVIDER explicitly) and works
with OpenAI, Anthropic, OpenRouter, and any OpenAI-compatible endpoint.

mnemonio init [dir]                        Create memory directory with MANIFEST.md
mnemonio scan [dir] [--team-dir <d>] [--json]               Display all memory file headers
mnemonio list [dir] [--type <t>] [--team-dir <d>] [--json]  List memories with descriptions + age
mnemonio search <query> [dir] [--team-dir <d>] [--json]     Find relevant memories (LLM required)
mnemonio distill [dir] [--force] [--json]  Run consolidation pass (LLM required)
mnemonio stats [dir] [--team-dir <d>] [--json]              File count, size, type breakdown
mnemonio prune [dir] [--max-age <days>] [--dry-run]         Remove stale/empty files

All commands default to the current directory if [dir] is omitted. Use --team-dir
to include a shared team memory directory in listings, search, and stats.

Library

npm install @memel06/mnemonio

Quick Start

import { createMnemonioStore } from '@memel06/mnemonio';

const store = createMnemonioStore({
  memoryDir: './.mnemonio',
});

// Create the memory directory and MANIFEST.md if they don't exist
await store.ensureDir();

// Inject memory context into your system prompt
const memoryPrompt = await store.buildPrompt();
const systemPrompt = `You are a helpful assistant.\n\n${memoryPrompt}`;

// List all memory files
const headers = await store.scan();
console.log(store.formatManifest(headers));

// Get stats
const stats = await store.stats();
console.log(`${stats.totalFiles} files, ${stats.totalBytes} bytes`);

With an LLM (search, extraction, distillation)

The quickest way is to use the built-in resolveLlm helper, which reads
MNEMONIO_API_KEY, MNEMONIO_BASE_URL, MNEMONIO_MODEL, and
MNEMONIO_PROVIDER from your environment and auto-detects the provider:

import { createMnemonioStore, resolveLlm } from '@memel06/mnemonio';

const store = createMnemonioStore({
  memoryDir: './.mnemonio',
  llm: resolveLlm(),
});

Or wire up your own callback for full control:

import { createMnemonioStore, type LlmCallback } from '@memel06/mnemonio';

const llm: LlmCallback = async ({ system, messages, maxTokens }) => {
  const response = await yourClient.chat({
    model: 'your-model',
    max_tokens: maxTokens,
    system,
    messages,
  });
  return response.text;
};

const store = createMnemonioStore({
  memoryDir: './.mnemonio',
  llm,
});

// Semantic search
const results = await store.findRelevant('database testing approach');

// Extract memories from a conversation
await store.extract({
  messages: [
    { role: 'user', content: "Don't mock the database in integration tests." },
    { role: 'assistant', content: 'Understood, I will use the real database.' },
  ],
});

// Consolidate (merge duplicates, prune stale entries)
await store.distill({ force: true });

Configuration

interface MnemonioConfig {
  /** Path to the memory directory */
  memoryDir: string;

  /** Optional path to a shared team memory directory */
  teamDir?: string;

  /** LLM callback -- required for search, extract, distill */
  llm?: LlmCallback;

  /** Name of the entrypoint file (default: "MANIFEST.md") */
  entrypointName?: string;

  /** Max lines to include from MANIFEST.md in prompts (default: 200) */
  maxEntrypointLines?: number;

  /** Max bytes to include from MANIFEST.md in prompts (default: 25000) */
  maxEntrypointBytes?: number;

  /** Optional structured logger */
  logger?: (msg: string, level: 'debug' | 'info' | 'warn' | 'error') => void;
}

The LlmCallback type accepts any provider. You wire it up once:

type LlmCallback = (params: {
  system: string;
  messages: ReadonlyArray<{ role: 'user' | 'assistant'; content: string }>;
  maxTokens: number;
}) => Promise<string>;

API Reference

Methods (no LLM required)

Method Returns Description
ensureDir() Promise<void> Create memory dir and MANIFEST.md if missing
scan(signal?) Promise<MemoryHeader[]> List all memory files with frontmatter metadata
readEntrypoint() Promise<EntrypointTruncation> Read MANIFEST.md with truncation info
buildPrompt() Promise<string> Build memory context string for system prompts
buildCombinedPrompt() Promise<string> Build prompt including team memory
stats(signal?) Promise<MnemonioStats> File count, total size, type breakdown, age range
formatManifest(headers) string Format headers as a human-readable manifest

Methods (LLM required)

Method Returns Description
findRelevant(query, opts?) Promise<RelevantMemory[]> Semantic search across memories
extract(config) Promise<ExtractResult> Extract memories from a conversation
distill(config?) Promise<DistillResult> Consolidate: merge duplicates, prune stale, tighten

Lock Management

Method Returns Description
readLastDistilledAt() Promise<number> Timestamp of last distillation
tryAcquireLock() Promise<number | null> Acquire distillation lock (null if held)
rollbackLock(priorMtime) Promise<void> Restore lock mtime on failure

Team Security

Method Returns Description
validateTeamWritePath(filePath) Promise<string> Resolve and validate path within team dir
isTeamPath(filePath) boolean Check if path is inside team directory

Memory File Format

Each memory is a markdown file with YAML frontmatter:

---
name: testing-approach
description: Team prefers integration tests with real DB over mocks
type: directive
tags: [testing, database]
---

Always use the real database for integration tests.

> reason: A prior incident where mocked tests passed but production broke on a
> schema change.

> scope: Use test containers or a dedicated test database. Never mock
> the DB layer in integration suites.

The MANIFEST.md file in the memory directory serves as the entrypoint. It
contains short one-line pointers to individual memory files. Mnemonio
auto-truncates it when injecting into prompts to stay within token budgets.

Memory Types

Type Purpose
identity Information about the user -- role, goals, preferences, expertise
directive Corrections and confirmed approaches -- behavioral guidance
context Ongoing work, decisions, timelines, incidents
bookmark Pointers to external systems, docs, dashboards, resources

Extended Frontmatter

Field Required Description
name No Human-readable slug for the memory
description No One-line summary shown in listings and manifests
type No identity, directive, context, or bookmark
tags No Freeform labels for cross-cutting concerns
expires No ISO date after which this memory is automatically excluded from all operations

License

MIT

Reviews (0)

No results found