stefmf39 downloadsA GitHub-style activity heatmap of your vault's file activity across the last 365 days.
A GitHub-style activity heatmap for Obsidian. Renders a 53×7 grid of the last 365 days in a sidebar pane, so you can see your writing cadence at a glance — then click any day to see the exact files you touched.
| Green | Heat | Sunset |
|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Three of the built-in palettes, in light and dark themes. Auto (theme accent) and Custom (any hex) round out the five options.
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".
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 heatmap via the grid ribbon icon (left sidebar) or the command palette entry Vault Pulse: Open heatmap.
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. |
| 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. |
| Custom hex color | #RRGGBB |
Only visible when palette is "Custom". |
| 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 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. Missing frontmatter falls back to the file's filesystem stat (ctime / mtime).
Vault Pulse runs entirely on your device. It does not make network requests, send telemetry, or transmit your notes anywhere.
To render the 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.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.MIT © 2026 Stefmf