Capture a work-log entry to the Notion Work Journal, a remote server cache, and a local mirror. Use whenever the user asks to log, note, record, or journal progress, a decision, or what they just did — and as the capture step invoked by /handoff.
Scanned 9/29/2026
npx -y skills add dgilford/ai-science-toolkit --skill worklog --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Worklog?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/dgilford-worklog)More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.
---
name: worklog
description: Capture a work-log entry to the Notion Work Journal, a remote server cache, and a local mirror. Use whenever the user asks to log, note, record, or journal progress, a decision, or what they just did — and as the capture step invoked by /handoff.
allowed-tools: mcp__claude_ai_Notion__notion-search mcp__claude_ai_Notion__notion-fetch mcp__claude_ai_Notion__notion-create-pages mcp__claude_ai_Notion__notion-update-page Bash Read
argument-hint: "[what to log]"
catalog:
order: 15
summary: 'Log a work entry to the Notion Work Journal + remote server cache + local `.ai/` mirror — the capture core invoked by `/handoff` and whenever you ask to log something.'
---
Capture one work-log entry into **three** targets. Distinguish two failure kinds:
- **Misconfiguration is loud.** If a target's env var is unset, that is a setup
error — **report it prominently** so it gets fixed, don't skip it quietly.
- **Transient failure is best-effort.** If a *configured* target is momentarily
unreachable (server down, Notion MCP disconnected), never block the caller —
note it and move on. The local mirror is the source of truth.
An end-of-day cloud routine summarizes the Notion raw entries into narrative
sections, so this skill only appends; it never summarizes.
## Compose the entry
Determine what to log:
- If the caller (e.g. `/handoff`) or the user supplied text or a summary, use it.
- Otherwise, summarize the current thread of work yourself: what got done, key
decisions, and the top next action.
Keep it tight: `summary` is 3-5 short bullets; `next` is the top 1-3 next actions.
**Redact secrets** — never put tokens, keys, passwords, or PII in the entry.
## Configuration
Two targets are configured via env vars (set in the `env` block of
`~/.claude/settings.json`, alongside the `ZOTERO_*` keys) — no personal
infrastructure is hardcoded in this skill. **If a var is unset, surface it
loudly as a setup error** (`worklog: <VAR> unset — this target is not
configured; set it in ~/.claude/settings.json`) so the gap gets fixed, rather
than silently dropping the target:
- `WORKLOG_SSH_TARGET` — `user@host` for the server cache (e.g. a Tailscale host).
- `WORKLOG_NOTION_HOME` — the Notion "Work Journal" home page id (raw entries are
appended to weekly sub-pages under it).
## 1 + 2 — Local mirror and server cache
Fill the two arrays with the composed content, then run:
```
DAY=$(date +%F)
PROJECT=$(basename "$(git rev-parse --show-toplevel 2>/dev/null || pwd)")
ENTRY=$(printf '{"ts":"%s","project":"%s","cwd":"%s","summary":%s,"next":%s}' \
"$(date -Iseconds)" "$PROJECT" "$PWD" \
'["bullet one","bullet two"]' \
'["next action one"]')
# durable local mirror (.ai/ is gitignored) — always written
mkdir -p .ai && printf '%s\n' "$ENTRY" >> ".ai/worklog-$DAY.jsonl"
# best-effort ship to server cache (non-fatal; skipped if WORKLOG_SSH_TARGET unset)
if [ -n "${WORKLOG_SSH_TARGET:-}" ]; then
printf '%s\n' "$ENTRY" | ssh -o ConnectTimeout=6 -o BatchMode=yes \
"$WORKLOG_SSH_TARGET" \
"mkdir -p ~/worklog/inbox && cat >> ~/worklog/inbox/$DAY.jsonl" \
&& echo "worklog: shipped to server" \
|| echo "worklog: server unreachable — kept local copy at .ai/worklog-$DAY.jsonl"
else
echo "worklog: WORKLOG_SSH_TARGET unset — server cache not configured; set it in ~/.claude/settings.json (kept local copy at .ai/worklog-$DAY.jsonl)" >&2
fi
```
## 3 — Append to the Notion weekly page
Use the Notion MCP tools. If `WORKLOG_NOTION_HOME` is **unset**, report it
loudly as a setup error (`worklog: WORKLOG_NOTION_HOME unset — Notion journal not
configured; set it in ~/.claude/settings.json`) — the local + server copies
still captured the entry. If the var is set but the **Notion MCP is not
connected**, that is a transient failure: note it and move on.
- **Work Journal home page id:** the value of `$WORKLOG_NOTION_HOME`.
- **Weekly page title convention:** `Week of YYYY-MM-DD (…)`, dated to the
**Monday** of the current week.
Steps:
1. Compute this week's Monday:
```!
python3 -c "import datetime; t=datetime.date.today(); print((t-datetime.timedelta(days=t.weekday())).isoformat())" 2>/dev/null || echo "(compute Monday manually)"
```
2. `notion-search` for `Week of <monday>`. If no matching page exists, create it
under the Work Journal home page (`notion-create-pages`, parent `page_id`
above) with this content — keep **Raw entries** as the last section (the
append relies on it being last):
```
*Daily summaries appear below, newest at top. Raw per-session entries collect under **Raw entries** at the bottom until the end-of-day routine summarizes them.*
---
## 🗂️ Raw entries (unprocessed)
*Session entries land here via `/handoff`. Cleared nightly after summarization.*
```
3. Append the entry with `notion-update-page` (`command: insert_content`,
`position: {"type":"end"}`) as a single bullet:
`- **HH:MM · <project>** — <one-line summary>. **Next:** <top next action>`
## Anti-Rationalization
| Excuse | Reality |
|---|---|
| "The server was down, so the log failed." | A *transiently* down server or disconnected Notion MCP is a non-event — the local `.ai/` mirror is the source of truth. Report which targets succeeded and move on. (An **unset** env var is different: report it loudly so config gets fixed.) |
| "This is minor, no need to log it." | If the user asked to log it, log it. Terse is fine; skipping is not. |
| "I'll summarize the whole day into one entry." | This skill only appends a single raw entry. The nightly routine does summarization — don't pre-empt it. |
| "I'll just write to Notion, the JSON mirror is redundant." | The mirror and server copy are the durable/offline record; Notion is the readable view. Write all reachable targets. |
## Verification
- [ ] A JSON line was appended to `.ai/worklog-<today>.jsonl` locally.
- [ ] The server push reported success, or its failure was reported (not swallowed) — including a loud setup error if `WORKLOG_SSH_TARGET` is unset.
- [ ] The bullet appears under **🗂️ Raw entries** on the current weekly page; or a loud setup error was reported if `WORKLOG_NOTION_HOME` is unset; or a transient MCP-disconnected note if the var is set but Notion is unreachable.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!