obsidian-brain
Sync Claude Code session transcripts into your Obsidian vault, generate end-of-day summaries that pull together your meetings, PRs, Jira work, and Claude sessions into one note, and extract actionable items as TaskNotes-formatted task files.
Installation
claude plugin install obsidian-brain@personio-claude-code-marketplace
Then set the vault path in your shell (~/.zshrc, ~/.bashrc, etc.):
export OBSIDIAN_BRAIN_VAULT_PATH="/absolute/path/to/your/obsidian/vault"
The plugin creates three folders under the vault on first use:
<vault>/claude-transcripts/YYYY/MM/DD/— one Markdown file per Claude Code session, written automatically at session end. Transcripts are nested by date so the folder stays navigable as it grows.<vault>/daily-summaries/— one Markdown file per day, produced by thesummarize-todayskill and refreshed in place on re-run.<vault>/tasks/— one TaskNotes-formatted note per actionable item extracted by thesummarize-todayskill (open Jira issues, open PRs, daily-note checkboxes, transcript follow-ups). Folder name is configurable viaOBSIDIAN_BRAIN_TASKS_FOLDER.
Requires: jq (brew install jq).
What does this plugin do?
Automatic transcript export (Stop + SessionEnd hooks)
The plugin writes a Markdown version of the running transcript into your Obsidian vault after every assistant turn (Stop hook) and once more at session end (SessionEnd) — no action needed.
Using Stop in addition to SessionEnd means the file stays current even if the session terminates in a way that doesn't fire SessionEnd (force-quit, crash, desktop window close). The script writes atomically (temp file + rename) so Obsidian never sees a half-written file.
What you need:
OBSIDIAN_BRAIN_VAULT_PATHset to your vault root.jqon yourPATH.
If the env var is unset or the vault doesn't exist, the hook exits quietly — no errors, no noise.
Quick Start:
# one-time setup
echo 'export OBSIDIAN_BRAIN_VAULT_PATH="$HOME/Documents/Obsidian Vault"' >> ~/.zshrc
source ~/.zshrc
# from then on, every session you end creates a file like:
# <vault>/claude-transcripts/2026/04/20/2026-04-20-1423-3f930ef3.md
Example output: 2026-04-20-1423-3f930ef3.md
---
session_id: '3f930ef3-6523-4867-918c-eb434846b159'
started_at: '2026-04-20T14:23:11.012Z'
ended_at: '2026-04-20T15:04:02.441Z'
cwd: '/Users/you/dev/my-project'
reason: 'exit'
message_count: 47
tags: [claude-code, transcript]
---
# Claude Code session — 2026-04-20-1423
- **Session:** `3f930ef3-6523-4867-918c-eb434846b159`
- **Working dir:** `/Users/you/dev/my-project`
- **Ended:** 2026-04-20T15:04:02.441Z (exit)
## User
Refactor the webhook retry logic to use exponential backoff.
## Assistant
I'll start by reading the current webhook handler and the retry config.
**Tool call: `Read`**
**Tool call: `Grep`**
...
Why would you want this?
- Your Claude sessions become searchable Obsidian notes alongside your engineering notes, meeting notes, and design docs.
- You can link to specific sessions from other notes (e.g., from a project page or a Jira ticket note) using
[[2026-04-20-1423-3f930ef3]]. - You get a persistent archive even if Claude Code's local transcript storage is cleared.
- Frontmatter (
session_id,cwd,message_count) makes filtering via Obsidian Dataview trivial.
summarize-today skill
Generates a single end-of-day summary note in your vault that aggregates everything you did across tools: today's Claude sessions, calendar meetings, PRs, Jira issues, and your existing daily note. Also extracts actionable items from those same sources and creates one TaskNotes-formatted note per task under <vault>/tasks/, deduped by external ID so re-runs refresh status instead of creating duplicates.
What you need:
OBSIDIAN_BRAIN_VAULT_PATHset (required).- Optional but recommended data sources — each is skipped cleanly if missing:
- Google Calendar MCP (for meetings)
ghCLI authenticated (for PRs)acliauthenticated (for Jira)OBSIDIAN_BRAIN_DAILY_NOTE_GLOBset to your daily note pattern (e.g.Daily Notes/{date}.md) to pull your own note into the summary- Obsidian CLI (
obsidian, 1.12+) — if installed, the skill triggers a sync after writing the summary so it propagates to your other devices, and prefers the CLI for vault-aware lookups (tags, properties, backlinks) over raw filesystem operations. The Obsidian app must be running for the CLI to work; if it isn't, the skill falls back silently and the on-disk write still serves as the source of truth.
Quick Start:
In any Claude Code session:
Summarize today
Or Wrap up my day, Daily recap, What did I ship today? — the skill triggers on any of these.
Example:
Claude will run the data-collection steps in parallel (gcal MCP, gh search prs --author=@me, acli for Jira, Glob on today's transcripts, Read on your daily note), then write a file at <vault>/daily-summaries/2026-04-20.md. Running the skill multiple times in a day refreshes the same file — no duplicates.
---
date: 2026-04-20
type: daily-summary
tags: [daily, claude-brain]
---
# Daily summary — 2026-04-20
## Highlights
- Shipped webhook retry with exponential backoff ([apps#33297](https://github.com/x/apps/pull/33297), PLAT-412)
- Unblocked EO team on attribute_logs consistency — root cause is a race in the event publisher
- Pair session with Milan on the product brief for ARM roles
## Meetings
- 09:30 — **Product review — ARM** (6 attendees) — agreed to cut scope to roles-only for Q2
- 14:00 — **1:1 with Ilja** — discussed hiring loop pacing
## Pull requests
### Authored
- [personio/apps#33297](https://github.com/personio/apps/pull/33297) — Webhook retry w/ exp backoff — **OPEN** (30 min ago)
### Reviewed
- [personio/monolith#88102](https://github.com/personio/monolith/pull/88102) — Fix null deref in PayConnect — MERGED
## Jira
- **PLAT-412** — Webhook retry hardening (In Review) — "Ready for review, see PR linked"
- **ARM-188** — Roles-only scope for Q2 (To Do)
## Today's tasks
### Jira
- [[plat-412]] — Webhook retry hardening — in-progress (updated)
- [[arm-188]] — Roles-only scope for Q2 — open (new)
### Pull requests
- [[personio-apps-33297]] — Webhook retry w/ exp backoff — in-progress (new)
## Claude Code sessions
### Webhook retry
- [[2026-04-20-0915-3f930ef3]] — Refactored retry config, switched to exponential backoff
### Attribute logs investigation
- [[2026-04-20-1130-7a22cd01]] — Traced the race to `AttributeLogPublisher.publish`
## From my daily note
> Focus: finish the webhook PR before standup; review Milan's brief in the afternoon.
> Energy: low morning, rebounded after lunch.
## Open threads
- Need to rerun the failed migration on staging before EOD tomorrow.
Each linked task note in <vault>/tasks/ follows the TaskNotes frontmatter format:
---
tags:
- task
title: Webhook retry hardening
status: in-progress
priority: high
due: 2026-04-25
contexts:
- "@work"
projects:
- "[[PLAT]]"
external_id: PLAT-412
source: jira
source_url: https://personio.atlassian.net/browse/PLAT-412
created: 2026-04-20
---
## Notes
Pulled in from Jira PLAT-412 — backend retry logic for the webhook delivery worker. Linked PR personio/apps#33297.
Re-running the skill on a later day refreshes only the frontmatter (status, priority, due, scheduled) of an existing task — your hand-written ## Notes and ## Meeting Notes content is preserved.
Why would you want this?
- One place to look at the end of the day — no stitching together calendars, PRs, tickets, and notes by hand.
- Outcome-focused, not activity-focused — the summary names what actually shipped, not what you fiddled with.
- Becomes a permanent, searchable Obsidian note you can link back to from weekly reviews, retros, or 1:1 prep.
- Open work surfaces as TaskNotes the moment it appears — Jira issues, open PRs, and daily-note checkboxes all flow into a single Obsidian task list you can manage with the TaskNotes plugin.
- Gracefully degrades — any missing data source is labeled "skipped" rather than failing the whole summary.
Configuration
| Env var | Purpose | Required |
|---|---|---|
OBSIDIAN_BRAIN_VAULT_PATH | Absolute path to your Obsidian vault root | Yes |
OBSIDIAN_BRAIN_DAILY_NOTE_GLOB | Path pattern under the vault for your daily note. Supported tokens: {date} → YYYY-MM-DD, {year} → YYYY, {month} → MM, {day} → DD. Flat layout: Daily Notes/{date}.md. Nested by year/month: Daily Notes/{year}/{month}/{date}.md. | No |
OBSIDIAN_BRAIN_TASKS_FOLDER | Vault-relative folder where TaskNotes-formatted task files are written. Defaults to tasks. Must resolve inside the vault. | No |
File layout
<vault>/
├── claude-transcripts/
│ └── 2026/
│ └── 04/
│ └── 20/
│ ├── 2026-04-20-0915-3f930ef3.md ← session export (hook)
│ └── 2026-04-20-1130-7a22cd01.md ← session export (hook)
├── daily-summaries/
│ └── 2026-04-20.md ← summarize-today skill output (one per day, overwritten on re-run)
└── tasks/
├── plat-412.md ← TaskNotes file per actionable item (deduped by external_id, frontmatter refreshed on re-run)
└── personio-apps-33297.md
Pre-existing flat transcripts (from before version 1.4.0) are migrated into the nested layout automatically on the next hook fire.
Troubleshooting
- Nothing is being exported. Check
echo $OBSIDIAN_BRAIN_VAULT_PATHin the shell Claude Code was launched from. The hook reads env from the Claude Code process, not the shell you use inside it. jq not foundin hook logs. Install withbrew install jq.- Hook timed out. Default timeout is 30s. Very long transcripts may exceed this — raise it by editing
hooks/hooks.jsonif needed. - Summary is missing a source. The skill prints which source was skipped and why. For
gh/acli, check they're authenticated. For Google Calendar, reconnect via/mcp.