Files
workspace/tools/habits.py

198 lines
5.5 KiB
Python
Executable File

#!/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 <name>' 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 <name> [desc] - Add a habit")
print(" habits check <name> - Mark habit done today")
print(" habits remove <name> - 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()