Skip to content

Commit 51b3309

Browse files
Thezenmonsterclaude
andcommitted
v0.2.3: Activation fixes, feedback infrastructure, health celebration
- Add --status flag to CLI add command (hypothesis/validated from CLI) - Add debug-info command for easy bug reporting - Add feedback/report links to init and doctor output - Fix serve error message (quilmem[mcp] not agentmem[mcp]) - Fix broken record.id snippets in README and landing page - Fix quickstart governance claims to match CLI capabilities - Fix broken doc link in quickstart - Redesign init next-steps to show governance + session continuity - Add MCP dependency check to init --tool - Fix Windows unicode crash on arrow/dash chars in memory titles - Exclude deprecated memories from conflict detection - Project-scope orphan detection in health check - Add health 100/100 celebration message + share nudge - Add MCP connection and docs confusion issue templates - Add troubleshooting docs page - Add feedback section to landing page Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c1d3cd6 commit 51b3309

14 files changed

Lines changed: 535 additions & 61 deletions

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,24 +38,10 @@ body:
3838
validations:
3939
required: false
4040
- type: textarea
41-
id: doctor-output
41+
id: debug-info
4242
attributes:
43-
label: Output of agentmem doctor
44-
description: Paste the output of `agentmem doctor` here.
43+
label: Output of `agentmem debug-info`
44+
description: Run `agentmem debug-info` and paste the output here. This captures your OS, Python version, DB state, and health in one go.
4545
render: shell
4646
validations:
4747
required: false
48-
- type: input
49-
id: os
50-
attributes:
51-
label: OS
52-
placeholder: Windows 11 / macOS 15 / Ubuntu 24.04
53-
validations:
54-
required: false
55-
- type: input
56-
id: python-version
57-
attributes:
58-
label: Python version
59-
placeholder: e.g. 3.12
60-
validations:
61-
required: false
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Docs Confusion
2+
description: Something in the docs was wrong, unclear, or didn't match what actually happened.
3+
title: "[Docs] "
4+
labels: ["docs"]
5+
body:
6+
- type: input
7+
id: page
8+
attributes:
9+
label: Which page or section?
10+
description: Link to the page, or describe where you were reading.
11+
placeholder: e.g. quickstart.md, README "60-Second Demo", landing page
12+
validations:
13+
required: true
14+
- type: textarea
15+
id: what-happened
16+
attributes:
17+
label: What was confusing or wrong?
18+
description: What did the docs say, and what actually happened when you followed them?
19+
placeholder: |
20+
The quickstart says to run X, but when I did, I got Y instead of Z.
21+
validations:
22+
required: true
23+
- type: textarea
24+
id: suggestion
25+
attributes:
26+
label: What would have been clearer?
27+
description: Optional. If you figured it out, what should the docs say instead?
28+
validations:
29+
required: false
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: MCP Connection Problem
2+
description: agentmem tools aren't showing up in your coding agent.
3+
title: "[MCP] "
4+
labels: ["setup", "mcp"]
5+
body:
6+
- type: dropdown
7+
id: tool
8+
attributes:
9+
label: Which coding agent?
10+
options:
11+
- Claude Code
12+
- Cursor
13+
- Codex
14+
- Windsurf
15+
- Other
16+
validations:
17+
required: true
18+
- type: textarea
19+
id: problem
20+
attributes:
21+
label: What's happening?
22+
description: What do you see (or not see) when trying to use agentmem tools?
23+
placeholder: |
24+
Tools don't appear in Claude Code. No errors, they just aren't there.
25+
validations:
26+
required: true
27+
- type: textarea
28+
id: config
29+
attributes:
30+
label: Your MCP config
31+
description: Paste the relevant section from your settings file.
32+
render: json
33+
validations:
34+
required: true
35+
- type: textarea
36+
id: debug-info
37+
attributes:
38+
label: Output of `agentmem debug-info`
39+
description: Run `agentmem debug-info` and paste the output here.
40+
render: shell
41+
validations:
42+
required: true
43+
- type: textarea
44+
id: serve-output
45+
attributes:
46+
label: Output of `agentmem serve` (if you tried it manually)
47+
description: Run `agentmem serve` in a terminal and paste any errors.
48+
render: shell
49+
validations:
50+
required: false
51+
- type: input
52+
id: os
53+
attributes:
54+
label: OS
55+
placeholder: Windows 11 / macOS 15 / Ubuntu 24.04
56+
validations:
57+
required: false

.github/ISSUE_TEMPLATE/setup_help.yml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,18 @@ body:
2828
validations:
2929
required: false
3030
- type: textarea
31-
id: doctor-output
31+
id: debug-info
3232
attributes:
33-
label: Output of agentmem doctor
34-
description: Paste the output of `agentmem doctor` here.
33+
label: Output of `agentmem debug-info`
34+
description: Run `agentmem debug-info` and paste the output here.
3535
render: shell
3636
validations:
3737
required: false
38-
- type: input
39-
id: os
38+
- type: textarea
39+
id: doctor-output
4040
attributes:
41-
label: OS
42-
placeholder: Windows 11 / macOS 15 / Ubuntu 24.04
41+
label: Output of agentmem doctor
42+
description: Paste the output of `agentmem doctor` here.
43+
render: shell
4344
validations:
4445
required: false

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ mem.add(type="decision", title="Use per-line atempo",
3636
status="active")
3737

3838
# Something you're not sure about yet
39-
mem.add(type="decision", title="Maybe try 2-second gaps before CTA",
39+
hypothesis = mem.add(type="decision", title="Maybe try 2-second gaps before CTA",
4040
content="Hypothesis from last session. Needs testing.",
4141
status="hypothesis")
4242

@@ -48,9 +48,9 @@ results = mem.search("audio mixing")
4848
context = mem.recall("building a narration track", max_tokens=2000)
4949

5050
# Lifecycle — promote what's proven, deprecate what's not
51-
mem.promote(record.id) # hypothesis -> active -> validated
52-
mem.deprecate(record.id, reason="Disproven by data")
53-
mem.supersede(old_id, new_id) # old points to replacement
51+
mem.promote(hypothesis.id) # hypothesis -> active -> validated
52+
mem.deprecate(hypothesis.id, reason="Disproven by data")
53+
mem.supersede(old.id, new.id) # old points to replacement
5454

5555
# Health check — is your memory system trustworthy?
5656
from agentmem import health_check

agentmem/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from .importer import import_markdown
66
from .models import MEMORY_TYPES, MEMORY_STATUSES, MemoryRecord
77

8-
__version__ = "0.2.0"
8+
__version__ = "0.2.3"
99
__all__ = [
1010
"Memory", "MemoryRecord", "MEMORY_TYPES", "MEMORY_STATUSES",
1111
"import_markdown",

agentmem/cli.py

Lines changed: 137 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,19 @@
22

33
from __future__ import annotations
44

5+
import io
56
import json
67
import sys
78

9+
# Windows cp1252 breaks on unicode chars like arrows/dashes in memory titles
10+
if sys.stdout and hasattr(sys.stdout, 'encoding') and sys.stdout.encoding and sys.stdout.encoding.lower() != 'utf-8':
11+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
12+
if sys.stderr and hasattr(sys.stderr, 'encoding') and sys.stderr.encoding and sys.stderr.encoding.lower() != 'utf-8':
13+
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
14+
815
import click
916

17+
from . import __version__
1018
from .core import Memory
1119
from .models import MEMORY_TYPES, MEMORY_STATUSES
1220

@@ -29,16 +37,20 @@ def main(ctx, db, project):
2937
@main.command()
3038
@click.option("--type", "mem_type", type=click.Choice(MEMORY_TYPES), required=True)
3139
@click.option("--title", required=True)
40+
@click.option("--status", "mem_status", type=click.Choice(MEMORY_STATUSES), default="active",
41+
help="Initial status (default: active).")
3242
@click.option("--tags", default="", help="Comma-separated tags.")
3343
@click.argument("content")
3444
@click.pass_context
35-
def add(ctx, mem_type, title, tags, content):
45+
def add(ctx, mem_type, title, mem_status, tags, content):
3646
"""Add a memory."""
3747
mem = _get_mem(ctx)
3848
tag_list = [t.strip() for t in tags.split(",") if t.strip()] if tags else []
39-
record = mem.add(type=mem_type, title=title, content=content, tags=tag_list, source="cli")
49+
record = mem.add(type=mem_type, title=title, content=content, tags=tag_list,
50+
source="cli", status=mem_status)
51+
status_label = f" ({record.status})" if record.status != "active" else ""
4052
click.echo(f"Added: {record.id}")
41-
click.echo(f" [{record.type}] {record.title}")
53+
click.echo(f" [{record.type}] {record.title}{status_label}")
4254
mem.close()
4355

4456

@@ -330,6 +342,13 @@ def health(ctx, days):
330342
if report.orphaned_supersedes:
331343
click.echo(f" ORPHANED: {len(report.orphaned_supersedes)}")
332344

345+
if report.health_score >= 100:
346+
validated = report.by_status.get("validated", 0)
347+
click.echo(f" Fully governed. 0 conflicts, 0 stale, {validated} validated rules.")
348+
click.echo(f" You're running a clean memory system. That's rare.")
349+
click.echo(f"\n If this helped, share your setup:")
350+
click.echo(f" https://github.com/thezenmonster/agentmem/discussions")
351+
333352
click.echo(f"\n{'=' * 50}")
334353
mem.close()
335354

@@ -378,6 +397,14 @@ def init(ctx, tool, proj):
378397
db_abs = str(Path(db_path).resolve()).replace("\\", "/")
379398

380399
if tool:
400+
# Check MCP dependency
401+
try:
402+
import mcp # noqa: F401
403+
except ImportError:
404+
click.echo(f" [!] MCP package not installed. Run:")
405+
click.echo(f" pip install quilmem[mcp]")
406+
click.echo()
407+
381408
click.echo(f" [3/4] MCP config for {tool}:\n")
382409

383410
if tool in ("claude",):
@@ -430,13 +457,28 @@ def init(ctx, tool, proj):
430457
click.echo(f"\n{'=' * 50}")
431458
click.echo(f" Done. Your memory DB is at: {db_abs}")
432459
click.echo(f" Project: {project}")
433-
click.echo(f"\n Next steps:")
434-
click.echo(f" agentmem add --type decision --title \"My first rule\" \"Description here\"")
435-
click.echo(f" agentmem search \"my rule\"")
460+
click.echo(f"\n Try the differentiators:")
461+
click.echo(f" # Add a rule you're certain about")
462+
click.echo(f" agentmem add --type decision --status validated \\")
463+
click.echo(f" --title \"Never force-push to main\" \"Enforced after incident.\"")
464+
click.echo(f"")
465+
click.echo(f" # Add something unproven")
466+
click.echo(f" agentmem add --type decision --status hypothesis \\")
467+
click.echo(f" --title \"Maybe batch DB writes\" \"Needs benchmarking.\"")
468+
click.echo(f"")
469+
click.echo(f" # Save your session so the next agent picks up where you left off")
470+
click.echo(f" agentmem save-session \"Working on auth refactor. Blocked on tokens.\"")
471+
click.echo(f" agentmem load-session")
472+
click.echo(f"")
473+
click.echo(f" # Check what your agent should trust")
436474
click.echo(f" agentmem health")
437475
if not tool:
438-
click.echo(f" agentmem init --tool claude # generate MCP config")
476+
click.echo(f"")
477+
click.echo(f" # Connect to your coding agent")
478+
click.echo(f" agentmem init --tool claude # or cursor, codex, windsurf")
439479
click.echo(f"{'=' * 50}")
480+
click.echo(f"\n Something break? {NEW_ISSUE_URL}")
481+
click.echo(f" Paste debug context: agentmem debug-info")
440482

441483

442484
@main.command()
@@ -536,16 +578,103 @@ def doctor(ctx):
536578
click.echo(f" All checks passed.")
537579
else:
538580
click.echo(f" Some checks failed. See above for fixes.")
581+
click.echo(f"\n Still stuck? {NEW_ISSUE_URL}")
582+
click.echo(f" Paste debug context: agentmem debug-info")
539583
click.echo(f"{'=' * 50}")
540584

541585

586+
ISSUES_URL = "https://github.com/thezenmonster/agentmem/issues"
587+
NEW_ISSUE_URL = f"{ISSUES_URL}/new/choose"
588+
589+
590+
@main.command("debug-info")
591+
@click.option("--json-output", "as_json", is_flag=True, help="Output as JSON for pasting into issues.")
592+
@click.pass_context
593+
def debug_info(ctx, as_json):
594+
"""Print system info for bug reports. Paste the output into a GitHub issue."""
595+
import platform
596+
from pathlib import Path
597+
598+
db_path = ctx.obj["db"]
599+
project = ctx.obj.get("project", "")
600+
601+
info = {
602+
"agentmem_version": __version__,
603+
"python_version": platform.python_version(),
604+
"platform": platform.platform(),
605+
"os": platform.system(),
606+
"db_path": str(Path(db_path).resolve()),
607+
"db_exists": Path(db_path).exists(),
608+
"project": project,
609+
}
610+
611+
# Check MCP
612+
try:
613+
import mcp
614+
info["mcp_installed"] = True
615+
info["mcp_version"] = getattr(mcp, "__version__", "unknown")
616+
except ImportError:
617+
info["mcp_installed"] = False
618+
619+
# DB stats if exists
620+
if info["db_exists"]:
621+
try:
622+
mem = Memory(path=db_path, project=project)
623+
stats = mem.stats()
624+
info["total_memories"] = stats["total"]
625+
info["db_size_kb"] = stats["db_size_kb"]
626+
627+
row = mem._conn.execute("SELECT MAX(version) FROM schema_version").fetchone()
628+
info["schema_version"] = row[0] if row else 0
629+
630+
from .governance import health_check as hc
631+
report = hc(mem._conn, project=project)
632+
info["health_score"] = report.health_score
633+
info["conflicts"] = len(report.conflicts)
634+
info["stale"] = len(report.stale)
635+
636+
by_status = {}
637+
for r in mem._conn.execute(
638+
"SELECT COALESCE(status, 'active') as s, COUNT(*) as c FROM memories GROUP BY s"
639+
):
640+
by_status[r["s"]] = r["c"]
641+
info["by_status"] = by_status
642+
643+
mem.close()
644+
except Exception as e:
645+
info["db_error"] = str(e)
646+
647+
if as_json:
648+
click.echo(json.dumps(info, indent=2))
649+
else:
650+
click.echo("agentmem debug-info")
651+
click.echo(f"{'=' * 50}")
652+
click.echo(f" agentmem: {info['agentmem_version']}")
653+
click.echo(f" Python: {info['python_version']}")
654+
click.echo(f" Platform: {info['platform']}")
655+
click.echo(f" DB: {info['db_path']} ({'exists' if info['db_exists'] else 'NOT FOUND'})")
656+
click.echo(f" Project: {info.get('project', '(none)')}")
657+
click.echo(f" MCP: {'yes' + (' v' + info.get('mcp_version', '?')) if info.get('mcp_installed') else 'not installed'}")
658+
if info.get("total_memories") is not None:
659+
click.echo(f" Memories: {info['total_memories']} ({info['db_size_kb']} KB)")
660+
click.echo(f" Schema: v{info.get('schema_version', '?')}")
661+
click.echo(f" Health: {info['health_score']:.0f}/100 | Conflicts: {info['conflicts']} | Stale: {info['stale']}")
662+
if info.get("by_status"):
663+
parts = [f"{s}: {c}" for s, c in sorted(info["by_status"].items())]
664+
click.echo(f" Status: {', '.join(parts)}")
665+
if info.get("db_error"):
666+
click.echo(f" DB Error: {info['db_error']}")
667+
click.echo(f"{'=' * 50}")
668+
click.echo(f"\n Paste this into a bug report: {NEW_ISSUE_URL}")
669+
670+
542671
@main.command()
543672
@click.pass_context
544673
def serve(ctx):
545674
"""Start MCP stdio server."""
546675
try:
547676
from .mcp_server import run_server
548677
except ImportError:
549-
click.echo("MCP support requires: pip install agentmem[mcp]", err=True)
678+
click.echo("MCP support requires: pip install quilmem[mcp]", err=True)
550679
sys.exit(1)
551680
run_server(db_path=ctx.obj["db"], project=ctx.obj.get("project", ""))

0 commit comments

Comments
 (0)