#!/usr/bin/env python3 """ habits - Simple habit tracker with streaks Track daily habits and maintain streaks. """ import json import sys from datetime import datetime, timedelta from pathlib import Path WORKSPACE = Path("/home/wdjones/.openclaw/workspace") HABITS_FILE = WORKSPACE / "data" / "habits.json" def load_data() -> dict: """Load habits data.""" HABITS_FILE.parent.mkdir(parents=True, exist_ok=True) if HABITS_FILE.exists(): with open(HABITS_FILE) as f: return json.load(f) return {'habits': {}, 'log': {}} def save_data(data: dict): """Save habits data.""" with open(HABITS_FILE, 'w') as f: json.dump(data, f, indent=2) def add_habit(name: str, description: str = ""): """Add a new habit to track.""" data = load_data() if name in data['habits']: print(f"Habit already exists: {name}") return data['habits'][name] = { 'description': description, 'created': datetime.now().isoformat(), 'active': True, } save_data(data) print(f"โœ“ Added habit: {name}") def check_habit(name: str, date: str = None): """Mark a habit as done for a date.""" data = load_data() if name not in data['habits']: print(f"Habit not found: {name}") print("Use 'habits list' to see all habits") return if date is None: date = datetime.now().strftime("%Y-%m-%d") if date not in data['log']: data['log'][date] = [] if name in data['log'][date]: print(f"Already checked: {name} on {date}") return data['log'][date].append(name) save_data(data) streak = calculate_streak(data, name) print(f"โœ“ {name} - done!") if streak > 1: print(f" ๐Ÿ”ฅ {streak} day streak!") def calculate_streak(data: dict, habit: str) -> int: """Calculate current streak for a habit.""" streak = 0 date = datetime.now() while True: date_str = date.strftime("%Y-%m-%d") if date_str in data['log'] and habit in data['log'][date_str]: streak += 1 date -= timedelta(days=1) else: break return streak def list_habits(): """List all habits with today's status.""" data = load_data() if not data['habits']: print("No habits tracked yet.") print("Use 'habits add ' to add one") return today = datetime.now().strftime("%Y-%m-%d") today_done = data['log'].get(today, []) print("\n๐Ÿ“Š Habits") print("=" * 40) for name, info in sorted(data['habits'].items()): if not info.get('active', True): continue done = "โœ…" if name in today_done else "โฌœ" streak = calculate_streak(data, name) streak_str = f"๐Ÿ”ฅ{streak}" if streak > 0 else "" print(f"{done} {name:20} {streak_str}") if info.get('description'): print(f" {info['description']}") print() done_count = len([h for h in data['habits'] if h in today_done]) total = len([h for h, i in data['habits'].items() if i.get('active', True)]) print(f"Today: {done_count}/{total} complete") def show_week(): """Show the past week's habit completion.""" data = load_data() if not data['habits']: print("No habits tracked yet.") return habits = [h for h, i in data['habits'].items() if i.get('active', True)] print("\n๐Ÿ“… Last 7 Days") print("=" * 50) # Header print(f"{'Habit':15}", end="") for i in range(6, -1, -1): date = datetime.now() - timedelta(days=i) print(f" {date.strftime('%a'):>3}", end="") print() # Each habit for habit in sorted(habits): print(f"{habit[:15]:15}", end="") for i in range(6, -1, -1): date = (datetime.now() - timedelta(days=i)).strftime("%Y-%m-%d") done = "โœ“" if date in data['log'] and habit in data['log'][date] else "ยท" print(f" {done:>3}", end="") streak = calculate_streak(data, habit) if streak > 0: print(f" ๐Ÿ”ฅ{streak}", end="") print() def remove_habit(name: str): """Remove a habit.""" data = load_data() if name not in data['habits']: print(f"Habit not found: {name}") return data['habits'][name]['active'] = False save_data(data) print(f"โœ“ Removed: {name}") def main(): if len(sys.argv) < 2: print("Usage:") print(" habits list - Show all habits") print(" habits week - Show weekly view") print(" habits add [desc] - Add a habit") print(" habits check - Mark habit done today") print(" habits remove - Remove a habit") print("") print("Examples:") print(" habits add exercise 'Daily workout'") print(" habits check exercise") list_habits() return cmd = sys.argv[1] if cmd == 'list': list_habits() elif cmd == 'week': show_week() elif cmd == 'add' and len(sys.argv) > 2: name = sys.argv[2] desc = ' '.join(sys.argv[3:]) if len(sys.argv) > 3 else "" add_habit(name, desc) elif cmd == 'check' and len(sys.argv) > 2: check_habit(sys.argv[2]) elif cmd == 'remove' and len(sys.argv) > 2: remove_habit(sys.argv[2]) else: print("Unknown command. Run 'habits' for help.") if __name__ == "__main__": main()