From ai-os-lite
Morning prep that writes a "Yesterday" recap and today's context to the journal page before you record. Creates the context that makes voice journal entries specific and actionable. Use when the user says "start day", "morning prep", or "/start-day".
How this skill is triggered — by the user, by Claude, or both
Slash command
/ai-os-lite:start-dayThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Prep today's journal page with yesterday's context — devlogs, carry-forward tasks, calendar, and evening reflection. This is Phase A of the daily loop: **AI preps the meeting before you journal.**
Prep today's journal page with yesterday's context — devlogs, carry-forward tasks, calendar, and evening reflection. This is Phase A of the daily loop: AI preps the meeting before you journal.
[from..today], with empty days between gaps rendered as a one-liner.vault-config/references/source-manifest.md.## Tasks Overview queries render tasks from type: task frontmatter. This skill does not write task lists./process-journal owns task note creation after the morning meeting.private: true) are silently excluded. The gather script also stamps private: true directly into excluded files' frontmatter as a one-way durable marker so future tools see the flag without re-traversing the project hub.Track all source calls per vault-config/references/source-manifest.md. The gather script tracks CLI sources automatically via source_manifest. MCP sources (Linear, QMD) are tracked by you in Step 2.
| Source | Used For | Criticality |
|---|---|---|
| Obsidian CLI | Read/write journal, daily hub, devlogs | REQUIRED |
| Obsidian MCP | Patch sections into journal + hub | REQUIRED |
| QMD Search | Devlog lookup (backup to glob) | MEDIUM |
| Todoist CLI | Today's tasks, carry-forward, Linear sync | HIGH |
| GWS Calendar | Today's calendar events | MEDIUM |
| Linear MCP | RS42 issues → Todoist sync | MEDIUM |
| Task Notes | Task note frontmatter (all projects) | MEDIUM |
/start-day → prep today's journal page
/start-day 2026-03-15 → prep a specific date
Reference: vault-config/references/tool-selection.md CLI for reads, writes, graph traversal, and property operations. MCP only for semantic search and section-level patching. DO NOT use mcp__obsidian-mcp-tools__get_vault_file for reads.
Collect all deterministic context data:
bash ${CLAUDE_PLUGIN_ROOT}/skills/start-day/scripts/gather_morning_context.sh [optional-date]
Parse the JSON output. It contains:
dates — today, yesterday (calendar), day namesfiles — journal/hub paths and existence flagsrecap_window — {from, to, beyond_lookback, days_empty[], days[]} where each day has {date, day_name, devlogs[], notes[]}. from == to means single-day window (the common case). beyond_lookback: true means the tiered probe (3/5/7 days) found no captured work — render the escape-hatch message instead of an empty recap.commits — {available, commits[]} where each commit has {sha, date, subject, kind, files[], projects[], areas[]}. Drives "What Moved Forward" and "What Changed Structurally".active_projects — [{slug, area, hub_path}, ...] — all status: active project hubs vault-wide.hot — [{slug, area, hub_path, last_activity_date, days_silent, area_priority_rank, recency_source, plan_path, latest_in_project_age_days}, ...] — projects with 0–3d recency. Suppressed at render — tracked for completeness only.warm — [{slug, area, hub_path, last_activity_date, days_silent, area_priority_rank, recency_source, plan_path, latest_in_project_age_days}, ...] — projects with 4–13d recency. Renders as a Warm sub-band under "Needs Attention".cold — same shape as warm[] plus a reason field — projects with ≥14d recency. Renders as a Cold sub-band under "Needs Attention".todoist — overdue + today tasksworkitems — external work-item integration (inert stub — connect Linear via MCP)evening — last night's reflection contentsource_manifest — what succeeded and what failedIf the script fails to execute, check that it has execute permission:
chmod +x ${CLAUDE_PLUGIN_ROOT}/skills/start-day/scripts/gather_morning_context.sh
The gather script can't call MCP tools. Fill in the gaps:
mcp__linear__list_issues(assignee="me", state="In Progress")
Record failure and continue if unavailable. Add - [ ] Linear in-progress — FAILED: {error} to the execution report.
If recap_window.days is empty AND recap_window.beyond_lookback is false, that's a surprise — the script found something to anchor the window on but no surfaceable content. Use QMD as a backup:
mcp__qmd__search(query="YESTERDAY_DATE", collection="vault")
Surface anything in */Dev Log/ or */Notes/ paths. Otherwise skip this step — beyond_lookback: true is a real signal, not a failure.
Task note discovery is handled by gather_morning_context.sh — read task_notes from the gather output. Each entry has path, status, priority, due_date, area, project, blocked_by. No skill-side bash loop is needed.
Check files.journal_exists and files.daily_hub_exists from the gather output.
If journal doesn't exist, create it:
bash ${CLAUDE_PLUGIN_ROOT}/skills/start-day/scripts/ensure_journal.sh TARGET_DATE
If daily hub doesn't exist, create it:
bash ${CLAUDE_PLUGIN_ROOT}/skills/start-day/scripts/ensure_daily_hub.sh TARGET_DATE
If files.journal_has_context is true: This is a re-run. Replace the existing context sections.
Read references/context-format.md for exact formatting rules.
/start-day writes one atomic patch into the morning journal entry — the entire ## Recent Accomplishments block (containing the three operational subsections + the ### Last Night's Reflection subsection) is replaced in a single MCP call. All task visibility comes from the ## Tasks Overview Bases queries the template already provides; this skill does not write task lists.
Why one atomic patch. Earlier iterations made two patch calls (one for Recent Accomplishments, a separate one for Last Night's Reflection). On re-runs after the first section had reflowed text, the second patch sometimes failed to find its H3 target and appended a duplicate H1 at the bottom of the file. Folding Last Night's Reflection into the Recent Accomplishments payload eliminates that drift. See Start-Day Iteration Findings 5-15 §5.
Replace the placeholder in ## Recent Accomplishments with a single payload containing the three operational subsections and the Last Night's Reflection H3.
Tone: Direct, factual, no celebration language. "You worked on X" not "Great work on X!". Match the chief-of-staff voice — concise, evidence-grounded, no padding.
Always render the window header line first (single-day or multi-day):
> **Recap Window**: M/D → M/D · N day(s) had no captured work (M/D, M/D)
If recap_window.beyond_lookback == true, render the escape-hatch and skip the three sections:
> No captured work in the last 7 days. Run `/start-day --since YYYY-MM-DD` to view earlier work.
Otherwise render three subsections in order. Omit any subsection that would be empty.
Ordering rule — applies to all three subsections:
Sort entries by area_priority_rank ascending (primary key), then by the per-subsection secondary key below. area_priority_rank is emitted by the gather script on every active_projects[], hot[], warm[], and cold[] entry (1={workarea-slug}, 2=rs42, 3={sidearea-slug}, 4=personal, 5=personal-finance/finance, 6=health, 7=career, 99=unknown). For entries derived from commits or devlogs (which carry an area field, not a direct rank), resolve the rank via the same mapping or by looking up the project in active_projects[].
Per-subsection secondary keys:
- **[[Area]]** *(area-level)*) before project entries; project entries in any stable order (alpha or evidence-volume).area_priority_rank ascending; secondary sort is days_silent ascending in Warm (freshest first), days_silent descending in Cold (longest-silent first).Area priority outranks the secondary key. Example: a 38-days-silent {SideArea} project sorts below a 34-days-silent {SideArea2} project, because {SideArea2} (rank 2) outranks {SideArea} (rank 3). See spec delta 5 worked example in Start-Day Morning Journal Render — Target Shape Spec from 5-13 Iteration.md §5.
Group commits[] (kind in docs|feat|fix) and recap_window.days[].devlogs[] by project. For each project with evidence, write a parent bullet with no inline body, then one tab-indented sub-bullet per distinct work item (commit cluster or devlog session):
- **[[Area]] / [[Project Hub]]**
- Work item one — concise factual description derived from commit subjects + devlog session_topics + (optionally) note titles. No celebration words.
- Work item two — …
Synthesis rules:
docs: / feat: / fix: prefix when reading commit subjects.6. Main Notes/ with only area: set), use a bare parent - **[[Area]]** *(area-level)* with sub-bullets underneath — same nested shape.Filter commits[] to those where at least one file in files[] matches a structural-change pattern:
2. Projects/*/{Project}/{Project}.md (project hub edits)3. Areas/*/Goals/*.md (goal hubs)Personal/*/*.md where filename equals folder name (personal project hubs){Project}/{Project}.mdCLAUDE.md, AGENTS.md, system-settings/Templates/* (vault config / templates)Group by area. Write a bare parent bullet per area and structural changes as tab-indented sub-bullets underneath:
- **[[Area]]**
- Structural change one — description.
- Structural change two — description.
Render two H4 sub-bands. Hot (hot[], 0–3d) is not rendered — projects that fresh don't need flagging; the band exists in the gather output for completeness and downstream tools.
Subsection header:
### Needs Attention
Warm band — H4 (4–13 days):
#### Warm — recently active, keep visible *(4–13 days)*
Each entry from warm[], sorted by area_priority_rank ascending (primary), then days_silent ascending (freshest first within band):
When recency_source == "in-project":
- **[[Area]] / [[Project Hub]]** — Nd since [[<last touched file or feature>]]. <Optional carry-forward context from prior journal>
When recency_source == "plan":
- **[[Area]] / [[Project Hub]]** — Nd via [[<plan-name>]] (plan-driven activity; latest in-project file is Md old). <Optional carry-forward context>
The <plan-name> is the basename of plan_path without .md (e.g. 2026-05-14-vault-setup-kit-update-story). The Md old value is latest_in_project_age_days from the entry — omit the parenthetical entirely if that field is null (no in-project file yet).
Cold band — H4 (≥14 days):
#### Cold — going stale, archive-sweep candidates *(14+ days)*
Each entry from cold[], sorted by area_priority_rank ascending (primary), then days_silent descending (longest-silent first within band):
- **[[Area]] / [[Project Hub]]** — `status: active` but {reason}. Last touched {last_activity_date} ({days_silent} days ago). <Optional carry-forward context>
The {reason} comes from the gather output's reason field on cold entries (either "no devlog or knowledge note in this project folder" for never-touched, or "no devlog or knowledge note dated within 14 days" otherwise).
When recency_source == "none" (never-touched project; last_activity_date == "never", days_silent == 999), omit the "Last touched … (… days ago)" tail entirely — the sentinels are not meaningful values. Render the bullet as:
- **[[Area]] / [[Project Hub]]** — `status: active` but {reason}. <Optional carry-forward context>
Carry-forward context (optional, non-mechanical):
For each entry rendered, check the prior morning journal (5. Resources/Personal/Journal/Morning Entries/<yesterday>.md)'s Needs Attention section. If the same slug appears there, copy any trailing prose annotation (e.g. "Load-bearing blocker for…", "{Contact} pricing follow-up still owed", "⚠ Hub Current Status empty — /project-sync overdue") onto today's entry. This is best-effort prose carry — if the annotation references a specific date or event that's stale (e.g. "today's Teach sister onboarding" the day after that event), drop or update it. Annotations are not derivable from gather data alone; absent a prior-journal source, omit them.
Omission rule:
If both warm[] and cold[] are empty, omit the entire ### Needs Attention H3. If only one band has entries, omit the empty sub-band but keep the H3.
Hot-band population does not affect this rule — Hot is never rendered, so a non-empty hot[] with empty Warm/Cold still omits the H3.
Wikilink resolution:
All wikilinks in this section follow §4c rules (basename for areas, hub_path basename for projects, full-path form for basename collisions). Plan-file wikilinks use the plan's basename — plans live under docs/superpowers/plans/ and basenames are date-prefixed and unique by convention; bare basename resolves.
Append the ### Last Night's Reflection subsection as the last H3 inside the Recent Accomplishments payload. This is part of the same patch call as 4a — do not make a separate patch_vault_file call targeting Last Night's Reflection.
Populated shape (when evening.found == true):
### Last Night's Reflection
> **Previous Evening**: [[5. Resources/Personal/Journal/Evening Entries/YYYY-MM-DD|Last Night's Evening]]
> - **Key insight**: <one-sentence pull from evening.content>
Empty-state shape (when evening.found == false):
### Last Night's Reflection
> **Previous Evening**: NO EVENING ENTRY
> - **Key insight**:
YYYY-MM-DD is yesterday's date — dates.yesterday from the gather output.evening.content.NO EVENING ENTRY is in literal caps — easy to grep, impossible to skim past. The Key insight: line stays present with empty value so the slot is structurally identical to the populated shape. Do not render > *No evening reflection from last night* — that soft form is deprecated.Wikilink resolution is a frequent source of broken links. Follow these three rules before emitting any [[...]]. See Start-Day Iteration Findings 5-15 §4 for failure cases.
Class A — Area wikilinks use basenames, not numeric-prefixed folders.
Area dashboard files live at 3. Areas/{NumericFolder}/{AreaName}.md (e.g. 3. Areas/1. {WorkArea}/{WorkArea}.md). The basename is the area name, not the numeric-prefixed folder.
| Area | ❌ Wrong | ✅ Right |
|---|---|---|
| {WorkArea} | [[1. {WorkArea}|{WorkArea}]] | [[{WorkArea}]] |
| {SideArea2} | [[2. {SideArea2}|{SideArea2}]] | [[{SideArea2}]] |
| {SideArea} | [[3. {SideArea}|{SideArea}]] | [[{SideArea}]] |
| Health & Fitness | [[4. Health & Fitness|Health]] | [[Health & Fitness|Health]] |
| Personal-Finance | [[5. Personal-Finance|Personal-Finance]] | [[Personal-Finance]] |
| Personal | (root folder, no numeric prefix) | [[Personal]] |
Rule: Numeric folder prefixes are filesystem-only. They never appear in wikilinks.
Class B — Basename collisions force a full-path alias.
When two project hubs share a basename (e.g. 2. Projects/2. {SideArea2}/Finances/Finances.md and 2. Projects/5. Personal-Finance/Finances/Finances.md), a bare [[Finances]] is ambiguous. Detect collisions by scanning active_projects[*].hub_path basenames for duplicates; for any colliding entry, use the full path with an alias:
[[2. Projects/2. {SideArea2}/Finances/Finances|{SideArea2} Finances]]
[[2. Projects/5. Personal-Finance/Finances/Finances|Personal-Finance Finances]]
Class C — Project hub wikilinks come from hub_path, not synthesis.
For every project, read the hub filename from active_projects[i].hub_path and use that basename as the wikilink target. Never synthesize from the project slug or display name — slugs may be hyphenated (copilot-studio) while the hub file may be Copilot-Studio.md, and the display name may have spaces that don't exist in the filename.
Procedure:
active_projects[i] row by slug match on the file's project: frontmatter.hub_path from that row, strip the .md extension, strip the directory prefix — the result is the wikilink target.hub_path basenames collide (Class B), emit the full path form instead.If no active_projects[] row exists for a slug (rare — usually a private project filtered out), skip the link rather than synthesizing one.
The full Recent Accomplishments payload, in order:
> **Recap Window**: M/D → M/D · N day(s) had no captured work (M/D, M/D) (or the beyond_lookback escape-hatch line).### What Moved Forward (omit if no entries).### What Changed Structurally (omit if no entries).### Needs Attention (omit if no entries).### Last Night's Reflection (always rendered — populated or sentinel; see 4b).Use MCP patch — one call:
mcp__obsidian-mcp-tools__patch_vault_file(
filename="5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD.md",
operation="replace",
targetType="heading",
target="Recent Accomplishments",
content="<window header + three H3 subsections + Last Night's Reflection H3>"
)
The patch replaces everything under ## Recent Accomplishments up to the next ## boundary (the --- divider before ## Tasks Overview), so the entire block is rewritten atomically.
After the patch lands, run the link audit script to verify every wikilink in the rendered journal resolves to exactly one vault file:
bash ${CLAUDE_PLUGIN_ROOT}/skills/start-day/scripts/audit_journal_links.sh TARGET_DATE
The script parses every [[...]] in the rendered Recent Accomplishments block and reports:
If any link fails, do not report success in Step 6. Surface the failed links in the execution report and re-render with the link resolver rules (4c) applied correctly.
/start-day does NOT write to the daily hub. The daily hub's **Today's priorities:** placeholder (- [ ] ...) stays until /process-journal fills it after the morning meeting.
Do not touch the daily hub file in Step 4.
After the atomic patch in 4d lands, scan the recap window for orphan clusters — multiple orphan notes from the same date and same project that look like one uncaptured session. Propose a retroactive devlog interactively so tomorrow's recap stops flagging them.
Cluster detection rules (operate on recap_window.days[].notes where orphan_candidate == true):
(date, project) tuple.[?] flag, do NOT propose (insufficient signal).project, so orphan_candidate is always false — they never reach this step).For each cluster (one batch of proposals, then per-cluster confirm):
Synthesize the proposal from the note titles, project, and a quick read of each note (use obsidian read path=... if titles aren't enough — keep it under 30s of reading per cluster). The title should be session-shaped (verb-first or theme-first), not a list of every note. Examples:
2026-05-05 - {Project} Vocabulary Lock — Four Layers, Lane-Based Render, Idea Ranch2026-05-04 - Hermes Pilot B Prep — Skill Portability and Heartbeat WiringPresent each cluster like this and ask the user to confirm:
Detected orphan cluster: 6 notes from 2026-05-05 (project: {project-slug})
Notes:
- [[Commitment Lifecycle and Daily Render — Vocabulary and Data Flow]]
- [[Solo Founder Hierarchy — Four Layers Beats Six]]
- [[Goal Initiative Project Task — Glossary for Solo Founder Operating System]]
- [[Idea Ranch — AI-Shepherded Idea Pipeline]]
- [[Initiative — Two Meanings in Current Vault and How to Resolve]]
- [[{Project} Lane-Based Daily Hub Architecture — Process-Journal v2 Proposal]]
Proposed retroactive devlog:
Title: 2026-05-05 - {Project} Vocabulary Lock — Four Layers, Lane-Based Render, Idea Ranch
Project: {project-slug}
Area: rs42
Tasks: (none — design session)
Body: wikilinks to all 6 notes + 1-line brief per note
Use AskUserQuestion (or equivalent interactive prompt) with options:
On Create:
Resolve the prior {project-slug} devlog (last devlog before the cluster date) and the next {project-slug} devlog (first devlog after the cluster date) for chain-linking. Prefer:
obsidian search "type: devlog project: <slug>" --limit 50
then sort by date and pick the immediate neighbors. QMD is a backup.
Write the devlog file at 2. Projects/{Area}/{Project}/Dev Log/{Title}.md using the Devlog Template's frontmatter shape:
---
date: <cluster-date>
type: devlog
status: capture
area: <area>
project: <slug>
session_topic: <verb-first description derived from title>
tasks: [] # design session — no task link
tags: [devlog]
---
Body content (concise — this is a retroactive reconstruction, not a fresh log):
# <Title>
> **Project**: [[Project Hub]]
> **Previous <project> devlog**: [[<prior devlog title>]]
> **Next <project> devlog**: [[<next devlog title>]]
> **Note**: Retroactively reconstructed by /start-day on <today> from an orphan cluster — the session happened but no devlog was written at the time.
## Notes produced this session
- [[<note 1 title>]] — <1-line brief from note's first paragraph or its own callout>
- [[<note 2 title>]] — <1-line brief>
- ...
## Why retroactive
These N notes share `date: <cluster-date>` and `project: <slug>` with no covering devlog. They cross-link and read as one design session. This devlog closes the orphan loop so tomorrow's recap groups them under their session intent.
Update the next devlog's Previous: link if it currently points to the prior devlog (now there's a new one in between). Same for the prior's Next: link if it pointed forward to the next. Use obsidian property:set or a small inline edit.
Confirm to the user: Created [[<Title>]] — N orphans now covered.
On Edit title: prompt for new title (single line), then proceed with steps 1–5 using the new title.
On Skip: move on to the next cluster.
After all clusters processed: report a one-liner summary in Step 6's execution report (e.g., - Orphan clusters: 2 detected, 1 created, 1 skipped).
For each Linear issue at the task level (not user stories), check if a Todoist mirror exists:
td task list --filter "search:RS4-xxx" --json
If no mirror exists, propose creation (batch — show all proposed tasks, then create):
td task add "Verb-first description (Linear RS4-xxx)" --project "{SideArea2}" --labels "@{sidearea2-slug}" --priority p2
Naming: Use the Linear title if verb-first and specific. Rewrite vague titles.
Completion: Todoist leads, external systems follow. If Linear shows Done but the Todoist mirror is open, flag it: *(Linear RS4-xxx, resolved upstream — close?)*
Merge the gather script's source_manifest with MCP tool results into a unified execution report (per vault-config/references/source-manifest.md):
Morning prep complete for YYYY-MM-DD.
**Yesterday**: N devlog sessions
**Carry-forward**: N tasks (M overdue)
Journal page prepped → [[5. Resources/Personal/Journal/Morning Entries/YYYY-MM-DD]]
Ready to record your morning journal.
---
### Execution Report
#### Sources
- [x] Obsidian CLI — journal read, daily hub read, N devlogs found
- [x] Todoist overdue/today — N items
- [ ] GWS Calendar — FAILED: auth token expired
- [x] Linear in-progress — N items
- [x] QMD Search — backup search, N results
- [x] Evening reflection — found
#### Warnings
- GWS integration unavailable. Run `gws auth login` to refresh.
- N devlogs found with no task linked.
#### Fix
- GWS: Run `gws auth login` to refresh OAuth token
Only include Warnings and Fix sections if there are actual issues. Script-tracked sources use source_manifest values; MCP-tracked sources (Linear, QMD) use your own tracking from Step 2.
| Scenario | Handling |
|---|---|
| Single-day window (yesterday only) | Render window header + three-section brief (What Moved Forward / Changed Structurally / Needs Attention) — omit any empty subsection |
| Multi-day window with gaps (e.g. Mon after long weekend) | Render window header summarizing gap days, then the three-section brief synthesized across the whole window — no per-day subsections |
| 4-day offline (3-day tier finds nothing, 5-day finds work) | Tiered lookback handles automatically — window extends to 5 days back |
| Full week off (5-day finds nothing, 7-day catches it) | Tiered lookback handles automatically — window extends to 7 days back |
Beyond 7 days idle (beyond_lookback: true) | Render escape-hatch message with --since invocation hint; skip the three-section brief |
| Day in window has only journal/daily/private files | Day appears in days_empty, not rendered as a section |
| Knowledge note exists but no covering devlog (orphan) | Appears as a - [?] sub-bullet under its project's parent bullet in What Moved Forward, with the *(orphan note — no devlog covered this)* suffix |
| Private project files | Silently excluded by gather script + per-file private: true stamp written to file frontmatter (one-way) |
| No Todoist tasks | "No overdue tasks" |
| Linear unavailable | Continue — note in source manifest |
| Journal already has context | Replace existing context (re-run safe) |
/process-journal)/process-journal)type: task frontmatter)/process-journal)npx claudepluginhub rs42-ai/ai-os-lite --plugin ai-os-liteGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.