A daemon that detects @ mentions in Obsidian notes, dispatches instructions to AI agents, and writes results back inline.
Project description
Note Watcher
A tool that detects @ mentions in Obsidian markdown notes stored in Git and dispatches instructions to configured agents — like Claude Code — that can read, modify, and reorganize your notes directly.
Write @agent_name do something in any note, and Note Watcher dispatches the instruction to the named agent. The agent can edit files, create new notes, restructure content, or make any other changes to your vault. The original instruction is then replaced with a completion marker (an HTML comment, invisible in rendered markdown) so it is never reprocessed:
<!-- @done agent_name: do something
Agent response summary goes here.
/@done -->
The real work happens in the commit: the agent's changes to your vault are committed back to Git. The completion comment is just a record that the instruction was processed.
Modes of Operation
| Mode | Use case |
|---|---|
| Daemon | Real-time file watching on macOS via a LaunchAgent |
| GitHub Action | One-shot batch processing on every push that changes .md files |
Requirements
- Python 3.10+
Installation
pip install notes-watcher
For development:
pip install -e ".[dev]"
Configuration
Copy the example config and edit it:
mkdir -p ~/.config/note-watcher
cp config.example.yml ~/.config/note-watcher/config.yml
The default config location is ~/.config/note-watcher/config.yml. You can override it with --config:
note-watcher watch --config /path/to/config.yml
Config reference
# Path to your Obsidian vault
vault: ~/Obsidian/MyVault
# Seconds to wait before processing after a file change
debounce_seconds: 1.0
# File patterns to ignore (glob syntax)
ignore_patterns:
- "*.excalidraw.md"
- ".trash/**"
# Agent definitions
agents:
summarizer:
type: echo # Returns instruction text unchanged
uppercase:
type: uppercase # Returns instruction text in uppercase
word_count:
type: command
command: "wc -w" # Runs a shell command, passes instruction via stdin
Agent types
| Type | Behavior |
|---|---|
echo |
Returns the instruction text unchanged |
uppercase |
Returns the instruction text in uppercase |
command |
Runs a shell command with instruction text on stdin, returns stdout |
Example: Using Claude Code as an agent
Configure a command agent that dispatches instructions to Claude Code:
agents:
claude:
type: command
command: "claude -p" # Dispatches instruction to Claude Code CLI
Claude Code runs with full access to your vault, so it can edit notes, create new files, and reorganize content — not just respond in a comment. Write @claude instructions in your notes:
@claude Summarize the key points of this meeting and add action items to my Tasks note
Daemon Mode
Daemon mode continuously watches your Obsidian vault for changes and processes @ mentions in real time.
Running manually
# Watch the vault specified in your config
note-watcher watch
# Override the vault path
note-watcher watch --vault ~/Obsidian/MyVault
# Enable verbose logging
note-watcher -v watch --vault ~/Obsidian/MyVault
Stop the daemon with Ctrl+C (SIGINT) or SIGTERM.
Installing as a macOS LaunchAgent
The included install script sets up Note Watcher as a LaunchAgent that starts on login and restarts on crash:
./scripts/install.sh
The script is idempotent and safe to run multiple times. It will:
- Detect the
note-watcherexecutable on your system - Generate a LaunchAgent plist from the included template
- Install it to
~/Library/LaunchAgents/ - Start the daemon
Logs are written to ~/Library/Logs/note-watcher/.
Uninstalling the LaunchAgent
./scripts/uninstall.sh
To also remove the log directory:
./scripts/uninstall.sh --clean
GitHub Action Mode
GitHub Action mode processes all pending @ instructions across the entire vault in a single batch run. This is useful for vaults stored in a Git repository.
CLI usage
note-watcher process --all --vault /path/to/vault
Setting up the GitHub Actions workflow
See examples/github-action/ for a complete, ready-to-copy example that uses Claude Code as the AI agent.
To set it up:
- Copy
examples/github-action/.github/into your notes repository - Add a
config.ymlto your notes repo (seeexamples/github-action/config.example.yml) - Add your
ANTHROPIC_API_KEYas a repository secret - Under Settings > Actions > General, set "Workflow permissions" to "Read and write permissions"
The workflow triggers on any push that modifies .md files, processes all unprocessed @ instructions, and commits the agent's changes back to your repository. It uses [skip ci] to prevent infinite loops.
See the Claude Code GitHub Actions documentation for more on setting up Claude Code in CI.
Running Tests
pytest
With coverage:
pytest --cov=note_watcher
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file notes_watcher-0.1.0.tar.gz.
File metadata
- Download URL: notes_watcher-0.1.0.tar.gz
- Upload date:
- Size: 19.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40d74d45c0ebb18145225b8b7a8393264177aad33e9b9840bc10c71852ba918f
|
|
| MD5 |
48c2627720b7d46ce13cc07d1a60359c
|
|
| BLAKE2b-256 |
208cac8929b41aba647fc1890450c925bb0d71738b042be8bf940f4e121e4324
|
Provenance
The following attestation bundles were made for notes_watcher-0.1.0.tar.gz:
Publisher:
publish.yml on britt/obsidian-notes-watcher
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notes_watcher-0.1.0.tar.gz -
Subject digest:
40d74d45c0ebb18145225b8b7a8393264177aad33e9b9840bc10c71852ba918f - Sigstore transparency entry: 1057438193
- Sigstore integration time:
-
Permalink:
britt/obsidian-notes-watcher@0d310716397f8b8c188aed06529817ffe62a0d4d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/britt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0d310716397f8b8c188aed06529817ffe62a0d4d -
Trigger Event:
release
-
Statement type:
File details
Details for the file notes_watcher-0.1.0-py3-none-any.whl.
File metadata
- Download URL: notes_watcher-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7ac1113100c11d95e1178a5116c98121e7b65caa8d1319d357d0dbd8216b2b20
|
|
| MD5 |
77b73c6b1d0e01725251b5359630ebcf
|
|
| BLAKE2b-256 |
d00f8ee92380fbef643e693eaa9d552b0f5301a9dc92a39eaeff1b95f7dc2889
|
Provenance
The following attestation bundles were made for notes_watcher-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on britt/obsidian-notes-watcher
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
notes_watcher-0.1.0-py3-none-any.whl -
Subject digest:
7ac1113100c11d95e1178a5116c98121e7b65caa8d1319d357d0dbd8216b2b20 - Sigstore transparency entry: 1057438201
- Sigstore integration time:
-
Permalink:
britt/obsidian-notes-watcher@0d310716397f8b8c188aed06529817ffe62a0d4d -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/britt
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@0d310716397f8b8c188aed06529817ffe62a0d4d -
Trigger Event:
release
-
Statement type: