Tempo

by Parham Forati
5
4
3
2
1
Score: 50/100

Description

Time tracking that lives in your notes and survives restarts — then slice the stats by any files, folders, or dates you choose.

Reviews

  • parham forati
    Reviewed on Sep 4th, 2026
    No review text provided.

Stats

1
stars
90
downloads
0
forks
10
days
2
days
2
days
0
total PRs
0
open PRs
0
closed PRs
0
merged PRs
0
total issues
0
open issues
0
closed issues
38
commits

Latest Version

2 days ago

Changelog

Tempo 1.3.0

This release focuses on making Tempo more convenient to use day-to-day: a smarter export, inline name suggestions, and a status bar that shows you what's running without opening any notes.

What's new in 1.3.0

  • Single export button with five formats. The two "Copy as table" and "Copy as CSV" buttons are replaced by one Export button that opens a menu of five clipboard formats: Table (Markdown), CSV, JSON, TOML, and YAML. Table and CSV reuse the existing flattened display, while JSON, TOML, and YAML export the raw tracker data with nesting preserved and the UI-only collapsed flag stripped — so they round-trip back into a tracker unchanged. The format list is extensible via a new registry (registerExportFormat/getExportFormats), making it easy to add more.

  • Suggested segment names. You can now define a list of segment names in Settings (one per line). When you focus the new-segment name box, the suggestions appear in a dropdown, filtered as you type. The dropdown supports mouse click, ArrowUp/ArrowDown/Enter/Escape navigation. Pressing Enter with a highlighted suggestion fills the name and starts the segment in one action — no extra keystrokes. The feature is opt-in and empty by default, so there's no change unless you add names.

  • Status bar indicators for running timers. Tempo now shows every currently running timer directly in Obsidian's bottom status bar. Each running timer appears as a compact pill: a red stop icon, the segment name, and a live ticking duration. Clicking the stop icon ends the timer (the note is saved automatically); clicking the name+duration opens the note. The tooltip (name + file path) appears above the pill on hover, never covering the status bar. The feature is scoped like the stats block — leave it empty to watch the whole vault, or add specific folders and files. A toggle in Settings enables/disables it. On mobile, the status bar collapses to a compact counter (⏱ N); tapping opens a menu with Open and Stop actions for each timer. Scanning is lazy (first tick after load), cached per file by modification time, and batched 8 reads at a time for performance. On vault modify/create/delete/rename, only the affected file is re-scanned.

Install

Community

You can install the plugin from the Obsidian community store: Obsidian Community

BRAT

Install BRAT, open the command palette and run "BRAT: Add a beta plugin for testing", then enter:

https://github.com/parhamf6/Tempo

Manual

Download main.js, manifest.json, and styles.css from the latest release and place them in:

/.obsidian/plugins/tempo/

Then enable "Tempo" in Settings → Community plugins.


Tempo builds on Ellpeck's Simple Time Tracker (MIT). Thanks, Ellpeck.

README file from

Github

Tempo

A modern, minimal multi-purpose time tracker for your Obsidian notes.

Tempo lets you track time directly inside your notes using a simple code block. Press the play button when you begin a task and the stop button when you finish — Tempo records the timestamps, saves them as plain JSON in your note, and shows you a clean table with per-segment and total durations. Because time is tracked purely by timestamps, a tracker keeps running even if you switch notes, close Obsidian, or shut down your device.

This version also adds Tempo Stats — a companion code block that aggregates the tracked time from the sources you choose into a clear summary: total time, number of tracked tasks, and number of files scanned.

https://github.com/user-attachments/assets/33966c3e-238d-4aa4-9967-61d2681e93fa


✨ Features

  • In-note time tracking — a tempo code block turns any note into a live timer with named segments.
  • Icon-based controls — start a segment with the play button (▶); while it's running the button becomes a stop button (⏹). No text buttons to hunt for.
  • Timestamp-based — segments are stored as start/end timestamps, so a running timer survives note switches, app restarts, and reboots.
  • Multiple segments — track as many named segments as you like; play, continue, rename, and delete them inline.
  • Copy as CSV — export the table to your clipboard for spreadsheets.
  • Totals & today — see the total tracked time and (optionally) the time tracked today.
  • Tempo Stats (tempo-stats) — aggregate the time tracked across the sources you pick:
    • You add sources yourself — a folder (optionally recursive, optionally filtered by a filename regex) or a single file. Tempo only scans what you tell it to; it does not scan your whole vault automatically.
    • Time rangeToday, 7 days, 30 days, or a custom range picked with a calendar date picker.
    • The panel shows, for the selected period: the total time tracked, the number of tasks (segments) tracked, and the number of files scanned. It also draws a daily bar chart and a per-task leaderboard as a visual breakdown. Refresh on demand or automatically as your vault changes.
  • Configurable formatting — moment.js timestamp format, CSV delimiter, fine-grained vs. compact durations, timestamp-style durations, segment order, and more (see Settings).
  • Public JavaScript API — query and aggregate your trackers from DataviewJS (see JavaScript API).

📦 Installation

  1. Open Settings → Community plugins.
  2. Make sure Restricted mode is off.
  3. Click Browse, search for Tempo, and click Install.
  4. Toggle Tempo on in your community plugins list.

Option B — Manual install (build from source)

Requirements: Node.js 18+ and npm.

# 1. Clone this repository
git clone <your-repo-url> Tempo
cd Tempo

# 2. Install dependencies
npm install

# 3. Build the plugin (produces main.js, manifest.json, styles.css at the root)
npm run build

Then copy the three built files into your vault:

  1. In your vault, open the folder <vault>/.obsidian/plugins/.
  2. Create a folder named exactly tempo (this must match the plugin id in manifest.json).
  3. Copy main.js, manifest.json, and styles.css into that tempo folder.
  4. Restart Obsidian (or toggle the plugin off/on), then enable Tempo under Settings → Community plugins.

⚠️ Folder name matters. Obsidian matches the plugin folder name to the id field in manifest.json. If the folder is named anything other than tempo, the plugin will not load.

📌 Requires Obsidian 1.13.0 or later. This version uses Obsidian's declarative settings API, so the minAppVersion in manifest.json is set to 1.13.0. On older Obsidian versions the plugin will not enable.


🤔 Usage

Tracking time

  1. Open the note where you want to track time.
  2. From the command palette, run Tempo: Insert Time Tracker (or type a ```tempo code block manually).
  3. Switch to Live Preview or Reading mode — the tracker renders as a table.
  4. Name the first segment (or leave it blank) and press the play button (▶).
  5. When you're done, press the stop button (⏹). The elapsed time is saved and shown in the table.
  6. Add more segments as needed; use the inline continue (▶), edit (✏️), and delete (🗑️) controls to manage them. Use Copy as CSV to export the table.

The tracker data lives as JSON inside the code block, so it stays in your note and syncs with the rest of your vault.

Viewing statistics

  1. In a note, run Tempo: Insert Time Tracker Stats from the command palette (or add a ```tempo-stats code block).
  2. In the stats panel:
    • Add sources — choose the folders/files you want included: a folder (optionally recursive, optionally filtered by a filename regex) or a single file. Only the sources you add are scanned.
    • Pick a time rangeToday, 7 days, 30 days, or a custom range with a calendar date picker.
    • The panel reports, for that period: the total time tracked, the number of tasks (segments) tracked, and the number of files scanned. It also draws a daily bar chart and a per-task leaderboard.
  3. Click Refresh to recompute, or let it refresh automatically as files in your vault change.

⚙️ Settings

Open Settings → Tempo (or search "Tempo" in Obsidian's settings search).

Setting Description
Timestamp display format moment.js format for timestamps in tracker tables (e.g. YY-MM-DD HH:mm:ss).
CSV delimiter Character used when copying a table as CSV. Useful for locales that use ; instead of ,.
Fine-grained durations Include days, months, and years in durations. When off, larger units roll into the hours display.
Timestamp durations Show durations as 12:15:01 instead of 12h 15m 1s.
Display segments in reverse order Show older segments at the bottom instead of the top.
Show total today Display the total time spent today in the tracker table.
Use monospaced font for times Use your monospaced font for the title timer so digits don't shift while counting.
Pretty-print tracker data Pretty-print the code block JSON (larger files, easier sync merges).

🔍 JavaScript API

Tempo exposes a public API for use with plugins like Dataview. Access it via the Obsidian app object:

app.plugins.plugins["tempo"].api;

Example — using DataviewJS to load every tracker in the vault and print the total duration of each:

// get the Tempo plugin api instance
let api = dv.app.plugins.plugins["tempo"].api;

for (let page of dv.pages()) {
    // load trackers in the file at the given path
    let trackers = await api.loadAllTrackers(page.file.path);

    if (trackers.length)
        dv.el("strong", "Trackers in " + page.file.name);

    for (let { section, tracker } of trackers) {
        // print the total duration of the tracker
        let duration = api.getTotalDuration(tracker.entries);
        dv.el("p", api.formatDuration(duration));
    }
}

Available functions:

  • loadTracker(json) — parse a single tracker's JSON.
  • loadAllTrackers(fileName) — load all trackers in a file.
  • getDuration(entry) / getTotalDuration(entries) — durations in ms.
  • getDurationToday(entry) / getTotalDurationToday(entries) — today's totals.
  • getDurationDate(entry, date) / getTotalDurationDate(entries, date).
  • getRunningEntry(entries) / isRunning(tracker).
  • formatTimestamp(timestamp) / formatDuration(totalTime) — using your settings.
  • orderedEntries(entries) — entries ordered per your segment-order setting.

👀 What it does (under the hood)

A time tracker is just a special code block that stores the timestamps of when you pressed the play and stop buttons. Because only timestamps are stored, you can switch notes, close Obsidian, or shut down your machine while a tracker is running — when you return, it's still running. The segment names, start times, and end times are saved as JSON in the code block and rendered as a table in preview/reading mode.


🛠️ Development

npm install        # install dependencies
npm run dev        # watch mode; rebuilds on change into main.js + test-vault
npm run build      # production build (tsc typecheck + minified esbuild bundle)
npm run lint       # eslint (includes Obsidian-specific rules)

The dev build also copies main.js, manifest.json, and styles.css into test-vault/.obsidian/plugins/simple-time-tracker/ so you can test against the bundled sample vault.


🙏 Credits

Tempo is built on top of ObsidianSimpleTimeTracker by Ellpeck (MIT licensed) — thanks for such a solid foundation to build on, and for kindly approving this fork.

📄 License

MIT — see the original project for license details.