feat(plugin): coding-focused custom-category setup script

mem0 auto-tags every memory with one or more `categories` from a
project-level list. The default list is consumer-oriented (food,
hobbies, music, ...), which produces meaningless tags for code
workflows.

Per-request `custom_categories` is not supported on the managed API,
so the fix has to be a one-time project-level configuration. New
script `setup_coding_categories.py` does this:

  - Dry-run by default: prints current vs proposed taxonomy, exits.
  - `--apply` flag actually calls `project.update(custom_categories=...)`.
  - Falls back gracefully when mem0ai SDK isn't installed or
    MEM0_API_KEY is missing/invalid (friendly error, no stack trace).

Recommended taxonomy:
  architecture_decisions, anti_patterns, task_learnings,
  tooling_setup, bug_fixes, coding_conventions, user_preferences

Skill clarification: `metadata.type` (agent-applied explicit tag,
used in filters) and `categories` (platform-applied auto-tag, used
in dashboards) are complementary; agent should keep using
`metadata.type` and not try to set `categories` per-request.

README: section under Step 2 explaining how to run the script.
This commit is contained in:
Mgeeeek
2026-05-08 21:30:42 +05:30
parent 0fd7cb9c5a
commit 2946fc9da5
3 changed files with 158 additions and 0 deletions
@@ -0,0 +1,142 @@
#!/usr/bin/env python3
"""Replace mem0's default category taxonomy with one tuned for coding workflows.
mem0 auto-tags every memory with one or more `categories`. By default the list
is consumer-oriented (food, hobbies, music, ...), which is meaningless for code.
This script replaces the project's category list with a coding-focused one.
The change is project-level (per the platform docs, per-request overrides are
not supported on the managed API). Run once per project; future memories will
be tagged using the new list automatically.
Usage:
python setup_coding_categories.py # dry-run: show current vs proposed, no changes
python setup_coding_categories.py --apply # actually call project.update()
Requires the mem0ai Python SDK and MEM0_API_KEY to be set.
"""
from __future__ import annotations
import argparse
import json
import os
import sys
CODING_CATEGORIES = [
{
"architecture_decisions": (
"Design choices, system structure, technology selection, trade-offs evaluated, "
"and architectural patterns adopted in the project."
)
},
{
"anti_patterns": (
"Approaches that failed, debugging dead-ends, common mistakes to avoid, "
"and lessons learned from things that didn't work."
)
},
{
"task_learnings": (
"Strategies and approaches that succeeded for specific tasks, including tooling "
"tricks, workflow shortcuts, and effective problem-solving patterns."
)
},
{
"tooling_setup": (
"Development environment, build tools, dependencies, package managers, deploy "
"pipelines, and configuration steps for the project."
)
},
{
"bug_fixes": (
"Specific bug fixes with root cause analysis, the fix applied, and how the bug "
"was diagnosed -- useful for recognising similar issues later."
)
},
{
"coding_conventions": (
"Code style, naming patterns, file organisation, error-handling conventions, "
"and team agreements about how code is written in this project."
)
},
{
"user_preferences": (
"User's stated preferences for tools, libraries, languages, formatting, "
"and ways of working."
)
},
]
def _print_categories(label: str, cats):
print(f"=== {label} ===")
if cats:
print(json.dumps(cats, indent=2))
else:
print("(none / using mem0 defaults)")
print()
def main() -> int:
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument(
"--apply",
action="store_true",
help="Actually call project.update(). Without this flag, runs in dry-run mode.",
)
args = ap.parse_args()
if not os.environ.get("MEM0_API_KEY"):
print("ERROR: MEM0_API_KEY is not set. Export it and try again.", file=sys.stderr)
return 1
try:
from mem0 import MemoryClient
except ImportError:
print(
"ERROR: the mem0ai Python SDK is not installed.\n"
"Install with: pip install mem0ai\n"
"Then re-run this script.",
file=sys.stderr,
)
return 1
try:
client = MemoryClient()
except Exception as e:
print(
f"ERROR initialising MemoryClient: {e}\n"
"Most commonly this is an invalid MEM0_API_KEY -- check the key at "
"https://app.mem0.ai/dashboard/api-keys",
file=sys.stderr,
)
return 1
try:
current = client.project.get(fields=["custom_categories"])
current_cats = current.get("custom_categories") if isinstance(current, dict) else None
except Exception as e:
print(f"ERROR fetching current categories: {e}", file=sys.stderr)
return 1
_print_categories("Current project categories", current_cats)
_print_categories("Proposed coding categories", CODING_CATEGORIES)
if not args.apply:
print("Dry-run only -- no changes made. Re-run with --apply to write.")
return 0
print("Applying coding categories...")
try:
response = client.project.update(custom_categories=CODING_CATEGORIES)
except Exception as e:
print(f"ERROR applying update: {e}", file=sys.stderr)
return 1
print("Done.", response if response else "")
return 0
if __name__ == "__main__":
sys.exit(main())