create_daily_note
Generate structured daily notes with smart population of incomplete tasks, goal-related items, quick wins, and relevant context for productivity management.
Instructions
Create today's (or specified) daily note with smart population.
Automatically pulls in:
Incomplete tasks from yesterday
Tasks related to active goals
A "quick win" task for low-motivation days
Context and insights
Args: date_str: Optional date in YYYY-MM-DD format (defaults to today)
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| date_str | No |
Implementation Reference
- src/coach_ai/daily_notes.py:159-295 (handler)The core logic of the create_daily_note MCP tool. It retrieves the vault, parses the date, checks for existing notes, fetches tasks, and calls the Obsidian vault method to create the note file.
async def create_daily_note(date_str: str = None) -> str: """Create today's (or specified) daily note with smart population. Args: date_str: Optional date in YYYY-MM-DD format (defaults to today) Returns: Success message with details """ vault = get_vault() if not vault: return "❌ Obsidian vault not configured. Set OBSIDIAN_VAULT_PATH environment variable." # Parse date if date_str: try: date = datetime.strptime(date_str, "%Y-%m-%d") except ValueError: return f"❌ Invalid date format. Use YYYY-MM-DD, got: {date_str}" else: date = datetime.now() # Check if note already exists if vault.daily_note_exists(date): note_path = vault.get_daily_note_path(date) return f"ℹ️ Daily note already exists: {note_path}" # Generate smart content db = await get_db() # 1. Get yesterday's incomplete tasks (if yesterday's note exists) yesterday = date.replace(day=date.day - 1) if date.day > 1 else None yesterday_tasks = [] if yesterday and vault.daily_note_exists(yesterday): yesterday_note = vault.read_daily_note(yesterday) if yesterday_note: yesterday_tasks = [ task["text"] for task in yesterday_note["tasks"] if not task["completed"] ] # 2. Get goal-related tasks goals_cursor = await db.execute( "SELECT goal, timeframe FROM goals WHERE status = 'active' LIMIT 3" ) goals = await goals_cursor.fetchall() # 3. Get user patterns for context facts_cursor = await db.execute( "SELECT fact, category FROM user_facts ORDER BY created_at DESC LIMIT 5" ) facts = await facts_cursor.fetchall() # 4. Build tasks list tasks = [] if yesterday_tasks: tasks.append("### Carried Over from Yesterday") for task in yesterday_tasks[:3]: # Limit to 3 tasks.append(task) tasks.append("") if goals: tasks.append("### From Your Goals") for goal in goals: # Simple task suggestion based on goal tasks.append(f"Work on: {goal['goal']} ({goal['timeframe']})") tasks.append("") # Add low-effort tasks section tasks.append("### Low-Effort Tasks") tasks.append("<!-- Add easy tasks for low-energy moments -->") tasks_text = "\n".join(tasks) if tasks else None # 5. Generate focus day_name = date.strftime("%A") if yesterday_tasks: focus = f"**Main Goal:** Continue momentum from yesterday\n**Backup Goal:** If stuck, work on goals instead" elif goals: focus = f"**Main Goal:** {goals[0]['goal']}\n**Backup Goal:** Make progress on any active goal" else: focus = "**Main Goal:** Define your priorities for today\n**Backup Goal:** Review and set your goals" # 6. Generate quick win (lowest activation energy task) current_hour = datetime.now().hour is_late_start = current_hour > 10 is_monday = day_name == "Monday" if is_late_start or is_monday: quick_win = "Open your todo list and read through it (just look, don't do anything yet)" else: quick_win = "Review yesterday's accomplishments and choose your first task" # 7. Generate context context_parts = [] if not vault.daily_note_exists(date): context_parts.append( "I noticed you haven't created your daily note yet, so I did it for you." ) if yesterday_tasks: context_parts.append( f"I pulled in {len(yesterday_tasks)} incomplete tasks from yesterday." ) if goals: context_parts.append( f"I added tasks related to your active goals: {', '.join(g['goal'] for g in goals[:2])}." ) if facts: context_parts.append("\n**What I know about you:**") for fact in facts[:3]: context_parts.append(f"- {fact['fact']}") if is_monday: context_parts.append( "\n**Pattern note:** It's Monday. I've added an extra-small quick win to help you get started." ) if is_late_start: context_parts.append( f"\n**Pattern note:** It's {datetime.now().strftime('%I:%M%p').lower()} - later than usual. No judgment! Let's start small." ) context = "\n".join(context_parts) if context_parts else None # Create the note note_path = vault.create_daily_note( date=date, focus=focus, quick_win=quick_win, tasks=tasks_text.split("\n") if tasks_text else None, - src/coach_ai/server.py:683-695 (handler)The MCP tool registration handler that exposes create_daily_note as an MCP tool. It acts as a wrapper around the daily_notes.create_daily_note implementation.
async def create_daily_note(date_str: str = None) -> str: """Create today's (or specified) daily note with smart population. Automatically pulls in: - Incomplete tasks from yesterday - Tasks related to active goals - A "quick win" task for low-motivation days - Context and insights Args: date_str: Optional date in YYYY-MM-DD format (defaults to today) """ return await daily_notes.create_daily_note(date_str) - src/coach_ai/obsidian.py:167-174 (helper)The underlying method within the Obsidian vault manager responsible for the actual file creation logic in the Obsidian vault.
def create_daily_note( self, date: datetime = None, focus: str = None, quick_win: str = None, tasks: list[str] = None, context: str = None, ) -> str: