stefmf694 downloadsA GitHub-style activity heatmap of your vault's file activity across the last 365 days.
A month calendar and a GitHub-style activity heatmap for Obsidian. The calendar puts a dot on each day for every note created or modified that day. The heatmap shows a year of writing cadence in a 53×7 grid. Click a day in either and the panel below lists its notes.
| Light theme | Dark theme |
|---|---|
![]() |
![]() |
The pane with the Auto palette, which follows your theme's accent. In the calendar, accent dots are notes created that day and grey dots notes last modified that day; the ringed day is today and the filled day is selected. Below, the selected day's notes in Created and Modified groups.
| Green | Heat | Sunset |
|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Three of the built-in palettes, in light and dark themes; each colors the calendar and the heatmap. Auto (theme accent) and Custom (any hex) round out the five options.
created: frontmatter, so a note edited later stays on the day it was made. It's a viewer: clicking a day never creates a note.Archive) or restrict to files carrying specific tags.src/i18n/ with English shipping today and community-contributed locales welcome.response=0.55s, dampingFraction=0.825).isDesktopOnly: false.Install from Settings → Community plugins → Browse → search "Vault Pulse". Vault Pulse 1.0 needs Obsidian 1.13 or later; older Obsidian versions are offered 0.3.4.
main.js, manifest.json, and styles.css from the latest release.<YourVault>/.obsidian/plugins/vault-pulse/ (create the folder if it doesn't exist).git clone https://github.com/stefmf/vault-pulse.git
cd vault-pulse
npm install
npm run build
Copy main.js, manifest.json, and styles.css into <YourVault>/.obsidian/plugins/vault-pulse/, or use npm run seed (see Development) which sets up a throwaway vault with the plugin pre-installed.
Open the pane via the grid ribbon icon (left sidebar) or the command palette entry Vault Pulse: Open calendar and heatmap. The calendar sits at the top, the heatmap under it, and the day's notes at the bottom.
Mon DD · N files.| Setting | Options | Notes |
|---|---|---|
| Activity source | Combined / Modified / Created | Default: Combined. A file counts for a day if either created OR updated matches that day. Applies to the heatmap; the calendar always shows both. |
| Modified date | Updated property, then file time / File time only | Default: Updated property, then file time. Which date counts as a note's last change, in both views. Pick file time only if your updated: property is a manual review date rather than one a plugin keeps current. |
| Color palette | Auto · Green · Heat · Sunset · Custom hex | Auto follows --interactive-accent. Named palettes use discrete hex values tuned for both light and dark themes. Colors the calendar too: its today ring, selected day and created dots use the palette's strongest color. |
| Custom hex color | Color picker | Only visible when palette is "Custom hex". |
| Window length | 90 / 180 / 365 days | Default: 365. Shorter windows narrow the grid but bring recent activity into sharper view. |
| Week starts on | Sunday / Monday | Default: Sunday (matches GitHub). |
| Exclude folders | Comma-separated path prefixes | e.g. Archive, _templates. Prefix matching: Archive excludes Archive/... but not My-Archive/.... Empty = include all. |
| Include tags | Comma-separated tag names (leading # optional) |
e.g. project, journal. If set, files must have AT LEAST ONE of these tags. Empty = include all. Reads both frontmatter tags: and inline #tags. |
| Show calendar | On / Off | Default: On. Toggles the month calendar. |
| Show heatmap | On / Off | Default: On. Toggles the heatmap with its pager, sparkline and legend. One of the two always stays on. |
| Show sparkline | On / Off | Default: On. Toggles the 30-day bar chart above the legend. |
| Show streak counter | On / Off | Default: On. Toggles the flame / trophy milestone row in the detail header. |
| Show mini stats | On / Off | Default: On. Toggles the week / month / year file counts under the streak row. |
| Show status bar widget | On / Off | Default: On. Toggles the streak + today's-files summary in Obsidian's status bar. |
Vault Pulse tracks consecutive active days across your whole vault (not capped to the window) and rewards consistency with a small milestone ladder:
| Day | Milestone |
|---|---|
| 7 | 🔥 first flame |
| 30 | 🔥🔥 second flame |
| 100 | 🔥🔥🔥 third flame |
| 365 | 🔥🔥🔥 🏆 trophy (grand celebration — gold confetti + bigger ripple) |
Additional:
· best N renders next to the current streak and persists across broken streaks. Flashes gold on ties / new records.◀ [range] ▶ above the heatmap steps backward through history one window at a time. Disabled when no older activity remains or when the grid ends on today. Reusing the existing Today → button returns you home in one click and resets the offset.🔥 N · [file] M in Obsidian's status bar shows the current streak (once it's ≥ 7 days) and today's file count. Clicking it opens the pane.N WEEK · M MONTH · K YEAR gives at-a-glance velocity (last 7 days / calendar month / calendar year).prefers-reduced-motion.Vault Pulse reads created and updated from each note's frontmatter when present. Supported formats: ISO 8601 (2026-04-13, 2026-04-13T12:34:56), SQL (2026-04-13 12:34:56), JS Date objects, and Unix millisecond epochs. A date-only value counts on that day in your own time zone.
created:, else the file's creation time (ctime). Prefer the frontmatter: tools that save by rewriting a file reset its creation time on every edit.updated:, else the file's modification time (mtime). With File time only, always mtime. Only the last modification is known, so a note shows on the day it was last changed. On a device that gets your vault through sync, mtime is when the sync wrote the file.Vault Pulse runs entirely on your device. It does not make network requests, send telemetry, or transmit your notes anywhere.
To render the calendar, heatmap and detail panel, the plugin reads:
app.vault.getMarkdownFiles() — required to discover which days had writing activity.created, updated, and tags / tag) via Obsidian's metadata cache — used for accurate date detection and the optional Include tags filter.ctime / mtime as fallbacks when frontmatter dates are absent, and mtime alone when Modified date is set to file time only.The plugin does not read note bodies. Files inside folders listed under Exclude folders are skipped entirely.
All state — settings, lifetime-best streak, recent windows — is stored locally in <vault>/.obsidian/plugins/vault-pulse/data.json.
Activity levels use quantile bucketing over the non-zero days in the 365-day window:
| Level | Condition |
|---|---|
| 0 | count = 0 (theme border color) |
| 1 | count ≤ p25 |
| 2 | p25 < count ≤ p50 |
| 3 | p50 < count ≤ p75 |
| 4 | count > p75 |
This adapts automatically: a light vault with ~1 note/day and a heavy vault with dozens/day both end up with meaningful bucketing. For the Auto and Custom palettes the colors are computed as alpha-blends of your base color, so empty days show through the theme background. For Green, Heat, and Sunset, the four levels are pre-tuned discrete hex values.
tests/README.md.AGENTS.md.src/i18n/en.json to <lang>.json, translate values (don't rename keys or change {placeholder} tokens), register in src/i18n/index.ts, open a PR. Obsidian's moment.locale() auto-picks the right bundle.The calendar's look follows Liam Cain's Calendar plugin. Vault Pulse uses none of its code.
MIT © 2026 Stefmf