- 12 Dec, 2025 *
Disclaimer: The methods described in this post involves fiddly complicated scripting stuff that probably need some prior experience with shell commands and automation to understand. Also this setup has also only been tested on my Linux machine. You might be able to get this working on Windows using Windows Subsystem for Linux or else translating the shell commands to PowerShell, but no guarantees.
This post also won’t really make any sense if you don’t know how Beeminder works.
Beeminding how many words you write each day is a good way to set up a daily journaling (among many other things) routine and eventually a daily/weekly/whatever interval you want [blogging routine](ht…
- 12 Dec, 2025 *
Disclaimer: The methods described in this post involves fiddly complicated scripting stuff that probably need some prior experience with shell commands and automation to understand. Also this setup has also only been tested on my Linux machine. You might be able to get this working on Windows using Windows Subsystem for Linux or else translating the shell commands to PowerShell, but no guarantees.
This post also won’t really make any sense if you don’t know how Beeminder works.
Beeminding how many words you write each day is a good way to set up a daily journaling (among many other things) routine and eventually a daily/weekly/whatever interval you want blogging routine. There’s even neat ways you can count up words in a Google Docs file covered by the official Beeminder blog here. Obsidian is a very good text editor / knowledge organiser with a massive plugin ecosystem which gives it support for all sorts of note taking and writing methods, all in plain text Markdown files.
So how about we combine the two?
The obvious way is to use the already existing Beeminder plugins:
- https://github.com/kevinvonjames/beeminder-obsidian-plugin
- https://github.com/kenzan100/beeminder-obsidian-word-count
But these are somewhat limited in how they operate. They can only track one file at a time, or you have to manually select an area of the text. I could fork them, or write my own, but I don’t really want to touch JavaScript1, and also as the files are just plain text Markdown, you can use standard Unix tools and scripts to analyse the files instead.
So I wrote a bunch of scripts instead
The core of my word count tracking setup is this Python script I wrote. It counts up the number of words using a simple ‘count the spaces’ algorithm (with some pre-processing to filter out Markdown formatting) in a set of files determined by a file glob set in a config file, and then sends the total to your Beeminder goal.
This allows us to set up multiple goals with separate word count tracking for each. For instance, separate goals for tracking drafts and published posts, or separate goals for different projects, or a goal for the global word count and specific goals for specific files. e.g.:
base_dir: "/path/to/your/obsidian/vault" # something like C:\\Users\\YourName\\Documents\\MyVault on Windows
beeminder:
username: "your_beeminder_username"
auth_token: "your_beeminder_token" # from https://www.beeminder.com/settings/account#account-permissions
goals:
- name: "drafts-wordcount"
glob: "Drafts/*.md"
- name: "posts-wordcount"
glob: "Posts/*.md"
If you don’t want to fiddle around with automation you can just run the script manually from Bash in the beeminder-wc directory like this:
# using the uv tool to handle dependencies/environment stuff for Python: https://docs.astral.sh/uv/
# make sure you've got uv installed and your config.yml file set up before running the script!
uv run -m beeminder_wc
Or if you just want to use the base Python command:
python -m beeminder_wc
You can set up the Python script to run periodically using a task automation tool like cron on Linux to keep the goals updated on a regular (5/10 minute) time interval, but what if you want to run the script on demand from within Obsidian, or set it to integrate with events in Obsidian? (e.g. typing stuff in, creating a file, closing Obsidian).
Turns out there’s a plugin for running shell scripts from Obsidian which lets you do that.

You can either invoke the script directly from the plugin, using a command like this:
cd /path/to/beeminder-wc && /path/to/uv run -m beeminder_wc
or write a wrapper script and place it into ~/.local/bin to make it neater. Then you can configure when exactly to run the script from within the plugin settings (the gear icon above the text box in the above screencap).

Presently I have the word count script set to run every 60 seconds (to serve as a crude WPM indicator) and when Obsidian closes to make sure all words are captured.
You aren’t limited to word count either, with CLI tools like Buzz you can write shell commands that automatically post values to Beeminder and run them when something happens in Obsidian. For instance, I want to keep track of the Daily Notes I create and make sure I create a new one each day. So I set up a Beeminder goal for it and figured out a shell command that counts up the number of files in the Daily directory and posts the total to Beeminder:
# the `buzz` tool posts the value piped into it to the beeminder goal
ls -1 /home/tom/Documents/Vaults/Beeminded/Daily | wc -l | buzz add dailyjournal
Then I set the Obsidian shell plugin to run it every time a file is created like this:

Limitations
The word count generated by the script doesn’t quite line up with the word count reported by Obsidian, and because the source code for the Obsidian word count isn’t public I can’t check what algorithm they use. My solution is to just switch to using the Novel Word Count Obsidian plugin which is close enough to the word count from my script.
Also, this script also doesn’t account for words being deleted, so if you add a big chunk of text, get the word count updated to include that text, and then delete it, it won’t track any words you add until you’ve added more words than the chunk of text you added. The technical solution to this would be to figure out a way of tracking all changes (additions and removals) to the text using git diff or something like that. The current workaround I use is just tracking total word count for the entire vault (which is mostly files where I’m appending words and rarely ever deleting stuff) and keeping track of word counts for things like completed blog posts separately.
And yeah I know these days with LLMs you can write JavaScript (or any other programming language) without ever having to actually ‘write’ JavaScript, but I like my fiddly hacked together pile of scripts and it Works For Me™.↩