Git-native memory for AI agents — markdown knowledge in .megg/ folders that travels with your repo. MCP server + CLI for Claude Code.
megg has 5 tools with clear, present input schemas and descriptions. All tools follow verb_noun naming convention (context, learn, init, maintain, state). Descriptions are reasonably detailed (97-276 chars, within baseline 34-392). However, several critical gaps reduce quality: (1) output schemas are not formally documented, responses are shaped ad-hoc with formatters but LLMs cannot see what fields to expect; (2) parameters lack domain-specific constraints (enums, ranges, patterns) where applicable; (3) no error recovery guidance in descriptions; (4) learn() and init() perform multiple responsibilities (learn creates entries AND updates files; init can analyze OR create files depending on parameters), violating single-responsibility principle; (5) error handling returns generic text responses without structured error classification or recovery hints; (6) state() tool mixes read/write/delete concerns. Individual tool scores vary 55-72; average is fair but below production baseline.
Load context chain and knowledge for current location. Auto-discovers .megg hierarchy, loads info chain, and includes knowledge (full if <8k tokens, summary if <16k, blocked if larger). Use topic parameter to filter knowledge by specific topic.
Initialize megg in current directory. Without content: analyzes project (or returns update analysis if already initialized). With content: creates .megg/info.md and optionally knowledge.md. Use update=true to update existing info.md (preserves created timestamp).
Add a knowledge entry to the nearest .megg/knowledge.md. Entries have type (decision/pattern/gotcha/context), topics for categorization, and content.
Analyze knowledge files for bloat, staleness, and duplicates. Returns a report with suggested cleanup actions.
Manage ephemeral session state for cross-session handoff. Call without args to read current state. Call with content to write state. Call with status='done' to clear state. State auto-expires after 48h.
Output schemas not formally documented. Responses are returned as text via formatters (formatContextForDisplay, formatMaintenanceReport, formatStateForDisplay) but LLMs cannot see what structured fields they should expect. This forces LLMs to parse unstructured text rather than access typed fields, increasing errors and token waste.
learn() and init() combine multiple concerns, violating single-responsibility principle. learn() both records entries AND updates knowledge.md file state. init() conditionally analyzes projects OR creates files depending on parameter combinations (info provided → create mode, info absent → analysis mode). This forces LLMs to reason about multiple outcomes per call.
state() tool mixes read, write, and delete operations into a single tool. Calling without args reads state; with content writes state; with status='done' clears state. This violates single-responsibility and confuses LLM intent, a single call signature performs three distinct actions depending on which optional parameters are set.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-21 | C | 60 | 2026-07-28+ | v2 |
| 2026-03-09 | D | 55 | - | v1 |
Enums not used where domain-constrained values exist. learn() accepts any string for 'type' parameter, though only 4 valid types exist. init() 'update' flag could accept 'yes'/'no' strings or arbitrary values. No validation prevents invalid entries at the input level.
Error handling returns generic text strings without actionable recovery guidance. All tools catch errors and return 'Error: <message>' or isError: true. No error classification (retryable vs user-fixable vs fatal), no suggested next steps, no valid alternatives offered when resources not found.
Parameter descriptions lack format and constraint specifications. 'path' parameter accepts any string with no guidance on whether absolute/relative/home-expanded paths are valid. 'topic' in context() has no upper bound on length or cardinality. 'content' in learn() and init() has no guidance on max length, format, or markdown validation.