#!/usr/bin/env python3 """ people - Personal CRM / people notes Keep notes about people you know. """ import json import sys from datetime import datetime from pathlib import Path WORKSPACE = Path("/home/wdjones/.openclaw/workspace") PEOPLE_FILE = WORKSPACE / "data" / "people.json" def load_people() -> dict: """Load people data.""" PEOPLE_FILE.parent.mkdir(parents=True, exist_ok=True) if PEOPLE_FILE.exists(): with open(PEOPLE_FILE) as f: return json.load(f) return {} def save_people(data: dict): """Save people data.""" with open(PEOPLE_FILE, 'w') as f: json.dump(data, f, indent=2) def add_person(name: str, context: str = None): """Add a new person.""" people = load_people() key = name.lower().replace(' ', '_') if key in people: print(f"Person already exists: {name}") return people[key] = { 'name': name, 'context': context, 'added': datetime.now().isoformat(), 'notes': [], 'tags': [], 'last_contact': None, } save_people(people) print(f"šŸ‘¤ Added: {name}") def add_note(name: str, note: str): """Add a note about someone.""" people = load_people() search = name.lower().replace(' ', '') # Find by partial match (normalize spaces) matches = [k for k in people if search in k.replace('_', '') or search in people[k]['name'].lower().replace(' ', '')] if not matches: print(f"Person not found: {name}") return key = matches[0] people[key]['notes'].append({ 'text': note, 'date': datetime.now().isoformat(), }) people[key]['last_contact'] = datetime.now().isoformat() save_people(people) print(f"šŸ“ Note added for {people[key]['name']}") def show_person(name: str): """Show info about a person.""" people = load_people() search = name.lower().replace(' ', '') # Find by partial match (normalize spaces) matches = [k for k in people if search in k.replace('_', '') or search in people[k]['name'].lower().replace(' ', '')] if not matches: print(f"Person not found: {name}") return person = people[matches[0]] print(f"\nšŸ‘¤ {person['name']}") print("=" * 40) if person.get('context'): print(f"Context: {person['context']}") if person.get('last_contact'): last = person['last_contact'][:10] print(f"Last contact: {last}") if person['notes']: print(f"\nšŸ“ Notes ({len(person['notes'])})") for note in person['notes'][-5:]: date = note['date'][:10] print(f" [{date}] {note['text'][:50]}") print() def list_people(): """List all people.""" people = load_people() if not people: print("No people yet. Add with: people add ") return print(f"\nšŸ‘„ People ({len(people)})") print("=" * 40) for key, person in sorted(people.items()): notes = len(person['notes']) context = person.get('context', '')[:20] print(f" {person['name']:20} {notes} notes {context}") print() def main(): if len(sys.argv) < 2: list_people() return cmd = sys.argv[1] if cmd == 'add' and len(sys.argv) > 2: name = sys.argv[2] context = ' '.join(sys.argv[3:]) if len(sys.argv) > 3 else None add_person(name, context) elif cmd == 'note' and len(sys.argv) > 3: name = sys.argv[2] note = ' '.join(sys.argv[3:]) add_note(name, note) elif cmd == 'show' and len(sys.argv) > 2: show_person(sys.argv[2]) elif cmd == 'list': list_people() else: print("Usage:") print(" people - List all") print(" people add [context] - Add person") print(" people note - Add note") print(" people show - Show person") if __name__ == "__main__": main()