#!/usr/bin/env python3 """ journal - Structured daily journaling Guided prompts for daily reflection and growth. """ import json import sys from datetime import datetime, timedelta from pathlib import Path WORKSPACE = Path("/home/wdjones/.openclaw/workspace") JOURNAL_DIR = WORKSPACE / "journal" PROMPTS = { 'morning': [ "What am I grateful for today?", "What would make today great?", "What am I looking forward to?", ], 'evening': [ "What went well today?", "What could have gone better?", "What did I learn?", "What am I grateful for?", ], 'weekly': [ "What were this week's wins?", "What challenges did I face?", "What do I want to focus on next week?", "How am I progressing on my goals?", ], } def get_journal_path(date: datetime = None) -> Path: """Get the journal file path for a date.""" if date is None: date = datetime.now() year = date.strftime("%Y") month = date.strftime("%m") day = date.strftime("%d") path = JOURNAL_DIR / year / month path.mkdir(parents=True, exist_ok=True) return path / f"{date.strftime('%Y-%m-%d')}.json" def load_entry(date: datetime = None) -> dict: """Load a journal entry.""" path = get_journal_path(date) if path.exists(): with open(path) as f: return json.load(f) return { 'date': (date or datetime.now()).strftime("%Y-%m-%d"), 'entries': [], } def save_entry(entry: dict, date: datetime = None): """Save a journal entry.""" path = get_journal_path(date) with open(path, 'w') as f: json.dump(entry, f, indent=2) def morning(): """Morning journal routine.""" print("\nšŸŒ… Morning Journal") print("=" * 40) print(f"Date: {datetime.now().strftime('%A, %B %d, %Y')}\n") entry = load_entry() responses = [] for i, prompt in enumerate(PROMPTS['morning'], 1): print(f"{i}. {prompt}") response = input(" → ").strip() if response: responses.append({'prompt': prompt, 'response': response}) print() if responses: entry['entries'].append({ 'type': 'morning', 'time': datetime.now().isoformat(), 'responses': responses, }) save_entry(entry) print("āœ“ Morning journal saved") def evening(): """Evening journal routine.""" print("\nšŸŒ™ Evening Reflection") print("=" * 40) print(f"Date: {datetime.now().strftime('%A, %B %d, %Y')}\n") entry = load_entry() responses = [] for i, prompt in enumerate(PROMPTS['evening'], 1): print(f"{i}. {prompt}") response = input(" → ").strip() if response: responses.append({'prompt': prompt, 'response': response}) print() if responses: entry['entries'].append({ 'type': 'evening', 'time': datetime.now().isoformat(), 'responses': responses, }) save_entry(entry) print("āœ“ Evening reflection saved") def quick(text: str): """Quick journal entry.""" entry = load_entry() entry['entries'].append({ 'type': 'note', 'time': datetime.now().isoformat(), 'text': text, }) save_entry(entry) print(f"āœ“ Journal entry saved") def show(days_ago: int = 0): """Show a journal entry.""" date = datetime.now() - timedelta(days=days_ago) entry = load_entry(date) print(f"\nšŸ“” Journal: {entry['date']}") print("=" * 40) if not entry['entries']: print("No entries for this day") return for item in entry['entries']: time = item['time'][11:16] if item['type'] == 'note': print(f"\n[{time}] šŸ“ {item['text']}") elif item['type'] in ('morning', 'evening'): emoji = 'šŸŒ…' if item['type'] == 'morning' else 'šŸŒ™' print(f"\n[{time}] {emoji} {item['type'].title()}") for resp in item.get('responses', []): print(f" Q: {resp['prompt']}") print(f" A: {resp['response']}") print() def stats(): """Show journaling statistics.""" total = 0 streak = 0 current_streak = True date = datetime.now() for i in range(365): check_date = date - timedelta(days=i) entry = load_entry(check_date) if entry['entries']: total += 1 if current_streak: streak += 1 else: current_streak = False print(f"\nšŸ“Š Journal Stats") print("=" * 40) print(f" Current streak: {streak} days") print(f" Total entries: {total} (last 365 days)") print() def main(): if len(sys.argv) < 2: print("Usage:") print(" journal morning - Morning prompts") print(" journal evening - Evening reflection") print(" journal - Quick entry") print(" journal show [days] - Show entry (0=today)") print(" journal stats - Statistics") show(0) return cmd = sys.argv[1] if cmd == 'morning': morning() elif cmd == 'evening': evening() elif cmd == 'show': days = int(sys.argv[2]) if len(sys.argv) > 2 else 0 show(days) elif cmd == 'stats': stats() else: # Quick entry text = ' '.join(sys.argv[1:]) quick(text) if __name__ == "__main__": main()