#!/usr/bin/env python3
"""
Vault Analytics Script
Analyzes the Obsidian vault to extract creation statistics.
"""
import os
from collections import Counter
from datetime import datetime
from pathlib import Path
def get_file_birth_time(filepath: Path) -> datetime:
"""Get the birth (creation) time of a file on macOS."""
stat = filepath.stat()
# On macOS, st_birthtime gives the creation time
return datetime.fromtimestamp(stat.st_birthtime)
def analyze_vault(vault_path: str):
"""Analyze the vault and return statistics."""
vault = Path(vault_path)
notes = list(vault.rglob("*.md"))
# Filter out system files
excluded = [".obsidian", ".git", "ZZ_Plantillas", ".trash"]
notes = [n for n in notes if not any(ex in str(n) for ex in excluded)]
if not notes:
print("No notes found!")
return
# Get creation times
note_times = []
for note in notes:
try:
birth = get_file_birth_time(note)
note_times.append((note, birth))
except Exception:
continue
# Sort by creation time
note_times.sort(key=lambda x: x[1])
# Stats
oldest = note_times[0]
newest = note_times[-1]
# Count by year-month
by_month: Counter[str] = Counter()
by_year: Counter[int] = Counter()
for _note, birth in note_times:
by_month[birth.strftime("%Y-%m")] += 1
by_year[birth.year] += 1
# Output
print("=" * 60)
print("π VAULT ANALYTICS")
print("=" * 60)
print(f"\nπ Total notes: {len(note_times)}")
print("\nποΈ OLDEST NOTE:")
print(f" {oldest[0].name}")
print(f" Created: {oldest[1].strftime('%Y-%m-%d %H:%M')}")
print(f" Path: {oldest[0].relative_to(vault)}")
print("\nπ NEWEST NOTE:")
print(f" {newest[0].name}")
print(f" Created: {newest[1].strftime('%Y-%m-%d %H:%M')}")
print("\nπ
NOTES BY YEAR:")
for year in sorted(by_year.keys()):
bar = "β" * (by_year[year] // 10) + "β" * ((by_year[year] % 10) // 5)
print(f" {year}: {bar} ({by_year[year]})")
print("\nπ NOTES BY MONTH (top 10):")
for month, count in by_month.most_common(10):
bar = "β" * (count // 5)
print(f" {month}: {bar} ({count})")
# Time span
span = newest[1] - oldest[1]
print(
f"\nβ±οΈ TIME SPAN: {span.days} days "
f"({span.days // 365} years, {(span.days % 365) // 30} months)"
)
print("\n" + "=" * 60)
if __name__ == "__main__":
import sys
vault_path = (
sys.argv[1]
if len(sys.argv) > 1
else os.environ.get(
"OBSIDIAN_VAULT_PATH",
"/Users/enriquebook/Personal/Obsidian/Secundo Selebro",
)
)
analyze_vault(vault_path)