-
Notifications
You must be signed in to change notification settings - Fork 149
Closed
Description
Summary
Add anonymous usage telemetry to Basic Memory using OpenPanel. Following the Homebrew analytics model: on by default with easy opt-out.
Motivation
We want to understand:
- What versions are in use
- What features are being used (MCP tools, CLI commands)
- What errors users encounter
- OS/Python version distribution
PyPI stats are unreliable, and we have no visibility into actual usage patterns.
Design Decisions
| Decision | Choice | Rationale |
|---|---|---|
| Backend | OpenPanel Cloud | Open source, privacy-first, Python SDK, $20/mo for 5K-100K events |
| Default | ON (opt-out) | Homebrew model - get meaningful data, easy to disable |
| Identification | Random UUID | Stored locally at ~/.basic-memory/.install_id, user can delete |
| First run | One-time notice | Not a prompt - just inform, then never show again |
What We'll Track
Events
| Event | Properties | Purpose |
|---|---|---|
app_started |
mode: "cli" | "mcp" |
Active usage |
mcp_tool_called |
tool: str |
Feature popularity |
cli_command |
command: str |
CLI usage patterns |
sync_completed |
entity_count, duration_ms |
Performance baseline |
error |
type, message (sanitized) |
Bug prioritization |
import_completed |
source: str |
Import feature usage |
Global Properties (every event)
app_versionpython_versionos(darwin/linux/windows)arch(arm64/x86_64)install_id(random UUID)
What We NEVER Collect
- Note content
- File names or paths
- Personal information
- IP addresses (OpenPanel doesn't store these)
User Experience
First Run Notice (shown once)
Basic Memory collects anonymous usage statistics to help improve the software.
This includes: version, OS, feature usage, and errors. No personal data or note content.
To opt out: bm telemetry disable
Details: https://memory.basicmachines.co/telemetry
CLI Commands
bm telemetry disable # opt out
bm telemetry enable # opt back in
bm telemetry status # show current state + what's collectedEnvironment Variable
export BASIC_MEMORY_TELEMETRY_ENABLED=false # disable via envImplementation
Files to Create
| File | Description |
|---|---|
src/basic_memory/telemetry.py |
Core telemetry module (client, track function, notice) |
src/basic_memory/cli/commands/telemetry.py |
CLI commands (enable/disable/status) |
tests/test_telemetry.py |
Unit tests |
Files to Modify
| File | Changes |
|---|---|
pyproject.toml |
Add openpanel dependency |
src/basic_memory/config.py |
Add telemetry_enabled (default True), telemetry_notice_shown fields |
src/basic_memory/cli/commands/__init__.py |
Register telemetry module |
src/basic_memory/cli/main.py |
Import telemetry commands |
src/basic_memory/mcp/server.py |
Add startup tracking + show notice |
src/basic_memory/cli/app.py |
Add startup tracking + show notice |
| MCP tool files | Add track() calls |
| CLI command files | Add track() calls |
Core Module (telemetry.py)
"""Anonymous telemetry for Basic Memory (Homebrew-style opt-out)."""
import platform
import uuid
from pathlib import Path
from openpanel import OpenPanel
from basic_memory import __version__
from basic_memory.config import ConfigManager
_client: OpenPanel | None = None
def get_install_id() -> str:
"""Get or create anonymous installation ID."""
id_file = Path.home() / ".basic-memory" / ".install_id"
if id_file.exists():
return id_file.read_text().strip()
install_id = str(uuid.uuid4())
id_file.parent.mkdir(parents=True, exist_ok=True)
id_file.write_text(install_id)
return install_id
def track(event: str, properties: dict | None = None) -> None:
"""Track an event. Fire-and-forget, never raises."""
try:
get_client().track(event, properties or {})
except Exception:
pass # Telemetry must never break the appDocumentation
Create a page at https://memory.basicmachines.co/telemetry documenting:
- Exactly what we collect
- What we never collect
- How to disable
- How to delete your data (delete
~/.basic-memory/.install_id)
Testing Strategy
- Unit tests for telemetry module (mock OpenPanel client)
- Verify opt-out disables tracking
- Verify notice only shows once
- Test env var override works
- Integration test for CLI commands
References
- OpenPanel Python SDK
- Homebrew Analytics
- Original discussion in Claude conversation
Metadata
Metadata
Assignees
Labels
No labels