name: worklog
description: Capture what was accomplished on a given day — drawn from the day's merged PRs (the complete picture, since work also happens in cloud sessions and other terminals) enriched by the live session (the why behind the slice it has context on) — and persist it to the user's Obsidian vault in three places: a session-summary note, a link from the project hub note, and a one-line entry in the daily note. User-scoped: reads the vault path from the user-level ~/.claude/maintainerd.json (journal.vault) and an optional per-repo project pointer from the repo's .claude/maintainerd.json. Use when the user wants to "log this session", "write up a dev log / worklog", "journal what we did", "record this work in my vault", "log what shipped today", or similar — optionally with a project name, vault path, or date. Do NOT use for general note-taking unrelated to the work, for project docs/specs, or when the user just wants an in-chat summary without writing to the vault.
Obsidian work-log
Capture a day's accomplishments — from the day's merged PRs (the complete picture; work also
happens in cloud sessions, other terminals, and scheduled agents the live conversation can't see)
enriched by the live session (the why behind the slice it has context on) — and persist it to
the user's Obsidian vault in three places: a session-summary note, a link from the project hub
note, and a one-line entry in the daily note.
This is the first journal-category skill, and the first Maintainerd skill that is user-scoped
rather than repo-scoped: it writes to the user's personal vault, which is the same across every repo
they work in. So its core setting — the vault — lives in a user-level config, not per-repo.
Append-safety (re-runs & multiple sessions) — READ FIRST
This is a hard requirement: the user runs Claude in both the terminal and the desktop app,
sometimes for the same project on the same day. The skill must only ever add to the daily note
and the project hub note — never replace, reorder, or drop existing content. Losing a prior entry is
the worst possible outcome.
Rules that make this safe:
- Targeted inserts only — never whole-file rewrites of existing notes. For the daily note and
the hub note, use
Edit to insert your one new line/link by matching a stable nearby anchor (a
heading like ## Notes, the existing "Dev logs" section, or the last bullet there). Do not use
Write on a file that already exists — Write replaces the whole file and is how prior entries
get clobbered. Write is only for creating a brand-new file (a day's session note or a missing
daily note).
- Read immediately before you edit. Re-
Read the daily note and hub note right before the
Edit, not from a stale read earlier in the session — another session (app/terminal) may have
written since. This shrinks the window where two runs could collide.
- One day's session note per project — extend it. Before creating a session note, glob the
project folder for an existing
Dev Log <today's date>*.md. If one exists, append new items
into its sections via Edit rather than creating a second note. Only Write a new note when none
exists for today.
- De-dupe, don't double-up. If the daily note already has a line for this project today, update
that line in place instead of adding a second. If the hub already links today's note, don't add
the link twice.
- Honest about the limit. Targeted inserts + read-right-before-write make sequential runs
(terminal now, app later) fully safe. Two truly simultaneous runs can still race, and Obsidian's
own sync can create conflict copies if two devices edit at once. There's no file locking here; if
you ever can't cleanly insert (anchor missing, content shifted unexpectedly), stop and tell the
user rather than overwriting.
Load config (two tiers)
worklog is user-scoped, so it reads two files — and, unlike repo-scoped skills, it does not
hard-stop if the repo-level config is missing.
- User-level
~/.claude/maintainerd.json — the required piece. Read journal.vault (the
Obsidian vault root). See ../../../core/reference/config-schema.md
("User-level config"). If the file or journal.vault is absent, ask the user for their vault
path and offer to write it to ~/.claude/maintainerd.json so future runs are configured — don't
hardcode a vault path. Optional keys: journal.projectsGlob (default Projects/**).
- Repo-level
.claude/maintainerd.json (optional for this skill) — if present, read config.repo
(the GitHub slug for the PR scan) and the optional config.journal pointer that maps this repo
to its vault project: config.journal.project (folder name under Projects/**) and/or
config.journal.hubNote (explicit vault-relative hub-note path). If there's no repo config, fall
back to gh repo view / the cwd folder name, and infer the project by matching that name under
journal.projectsGlob.
Inputs
Invoked as /worklog [project-or-path]. Interpret the argument:
- A project name → find its folder/hub note under
<vault>/<projectsGlob>.
- An absolute directory path → treat it as the project folder; derive the vault as the nearest
ancestor containing a
.obsidian/ directory (this can override journal.vault).
- A vault path (a dir containing
.obsidian/) → use it as the vault and infer the project.
- Empty → infer the project from the current working directory (git repo / folder name), then
resolve it under the configured vault.
If the project can't be resolved unambiguously, ask which project/folder before writing anything.
Never guess a target and write to the wrong place.
Default behavior: blend both sources (step 2) — the day's merged PRs for completeness, enriched
by the live session. Flags narrow that:
--no-prs / --session-only → skip the PR scan; summarize just the live conversation.
--from-prs (or "log what shipped today") → PRs only; don't draw on the live session (work happened
elsewhere, e.g. a web session).
- A date (
YYYY-MM-DD, "yesterday", "today") → the log date. Defaults to the current date.
--repo owner/name → override the repo (otherwise from config.repo, gh, or the hub note).
--author @me → only the user's own PRs (default: every PR merged that day, so parallel/automated
work is captured too).
Workflow
1. Resolve targets (read before writing)
- Vault —
journal.vault (or an explicit path argument). Confirm it has a .obsidian/ directory.
- Daily-note location & format — read
<vault>/.obsidian/daily-notes.json (fall back to
periodic-notes.json, then core defaults). Take folder and format (a moment.js date format,
e.g. YYYY/MM/YYYY-MM-DD) and a template if present. Build today's path from the current date
in the environment context. Example: folder Daily, format YYYY/MM/YYYY-MM-DD, date 2026-06-30
→ <vault>/Daily/2026/06/2026-06-30.md.
- Project folder + hub note — use
config.journal.hubNote if set; else config.journal.project
(or the inferred repo name) to locate the folder under journal.projectsGlob. The hub note is the
.md whose basename matches the folder, or the folder's most index-like note (a * - MOC.md /
<Project>.md). Read it so you can add a link without clobbering existing content.
2. Gather the material, then summarize
By default gather both and blend: merged PRs are the source of truth for what shipped; the live
session adds the why for the slice it has context on.
A. Scan the day's merged PRs (skip only on --no-prs/--session-only):
- Resolve the repo:
--repo; else config.repo; else gh repo view --json nameWithOwner -q .nameWithOwner; else parse a github.com/... URL from the hub note's front-matter. If none
resolves (or gh is unavailable), skip the PR scan, fall back to session-only, and say so.
- Fetch the day's merges for the resolved date, timezone-aware so late-evening merges don't roll
into the next UTC day:
TZ_OFFSET=$(date +%z); TZF="${TZ_OFFSET:0:3}:${TZ_OFFSET:3}"
gh pr list --repo <owner/name> --state merged --limit 200 \
--search "merged:<DATE>T00:00:00${TZF}..<DATE>T23:59:59${TZF}" \
--json number,title,url,mergedAt,labels,author,body
Add --author @me only if requested. Zero PRs → say so and offer to widen the date or fall back to
session-only; don't invent content.
- Read the PR bodies for rationale/caveats/follow-ups — that's where decisions live. Cite each as
#<number>. (If daily-changelog is in use, the per-day files under config.paths.changelogDir
are an already-triaged shortcut.)
B. Gather live-session context (skip only on --from-prs): from this conversation, what was
actually done here and why — the decisions, dead ends, and gotchas that never make it into a PR body.
C. Blend, keyed on PR number: every merged PR appears in Shipped; for PRs this session worked
on (match by #number) use the richer session context; for PRs from elsewhere (cloud/other terminals,
automated/scheduled PRs) summarize from titles/bodies and keep routine ones brief. Note source limits
honestly (e.g. "PRs #X/#Y were done in a web session — detail is from their descriptions").
Write a tight, scannable summary — signal, not length:
# Dev Log — <YYYY-MM-DD>: <short topic>
<one-sentence framing of the arc>
## Shipped
- <what landed, grouped logically; cite PRs/issues as #123 and link related notes>
## Decisions / gotchas worth remembering
- <non-obvious choices, root causes, "why", traps that cost time>
## Follow-ups
- [ ] <open threads, deferred work, things to verify — as checkboxes>
---
Related: [[<Project hub>]] · [[<other relevant notes>]]
Guidance: pull concrete identifiers (PR/issue numbers, file/area names, commands, decisions); prefer
"what changed and why it mattered" over a play-by-play. Decisions/gotchas is the highest-value
section. Follow-ups use GitHub-flavored - [ ] task syntax, never the Unicode ballot box. Use
[[wikilinks]] to the hub and related notes. Be honest about what's unverified or pending.
3. Write the three artifacts
Follow Append-safety for all of these — glob/Read first, Edit (insert) into existing files,
Write only to create a new file.
- Session-summary note — first
Glob <ProjectFolder>/Dev Log <YYYY-MM-DD>*.md.
- None today →
Write a new <ProjectFolder>/Dev Log <YYYY-MM-DD> - <short topic>.md.
- One exists →
Read, then Edit to append into the matching sections. Don't recreate it.
- Hub-note link —
Read the hub. Find a Dev logs / Session logs section (or add one just
below the title/front-matter). If today's note is already linked, do nothing; else Edit to insert
- [[<note basename>]]. Never Write the hub.
- Daily-note line — compute the path from the daily-notes config + current date.
- Missing →
Write it from the configured template (fill date tokens for the current date),
or a minimal note with the date heading and a ## Notes section.
- Exists →
Read, then Edit to insert - **<Project>**: <one-line summary> — [[<note basename>]] into the notes section. If a line for this project + today is already there, update
it in place instead of adding a second.
4. Report
Tell the user exactly what was written, with vault-relative paths: the new/updated session note, the
hub link, and the daily-note line (show that one-line entry verbatim so they can eyeball it). Don't
paste the whole session note back.
Conventions
- One session note per (project, day). Re-running extends it (found by globbing
Dev Log <date>*).
- Never clobber.
Edit-insert into existing notes; reserve Write for brand-new files. Read
right before editing. Preserve front-matter, headings, and existing bullets.
- Match the vault's voice. Mirror heading levels, bullet vs. checkbox usage, and wikilink style
already present in the project's notes.
- Vault-relative wikilinks use the note basename (Obsidian resolves them), not absolute paths.
- Dates come from the environment's current date; format the daily-note path per the vault's
daily-notes config, not a guessed convention.
Edge cases
- No
journal.vault configured — ask for the vault path and offer to write it to the user-level
config; don't hardcode one.
- No daily-notes config / unusual format — fall back to
<vault>/Daily/<YYYY-MM-DD>.md; mention
the assumption in the report.
- No hub note — if the project folder has no obvious hub
.md, create a minimal one
(# <Project> + a Dev logs section) or ask; don't silently skip the link.
- Multiple vaults / ambiguous project — ask rather than guess.
- Thin session — if little of substance happened, say so and write a short note (or ask whether to
skip) instead of padding.
- Sensitive content — don't write secrets, tokens, or credentials into the vault even if they
appeared in the session; summarize around them.