How mikebarkmin/ulauncher-obsidian works
1. What this repository is
- A Python Ulauncher extension for interacting with an Obsidian vault on the local filesystem.
- It adds launcher commands to open notes by name, search note contents, open today’s daily note, and quick-capture text into a note.
2. Top-level architecture
- The repo is split into:
- a small extension entrypoint (main.py)
- reusable helper modules under src/
- extension metadata/configuration (manifest.json, versions.json)
- development/test fixtures (test-vault/)
- There is no server/backend; all operations are local file reads/writes against the Obsidian vault.
3. Extension runtime boundary
- main.py is the likely integration point with the Ulauncher extension API.
- It receives launcher input, delegates to helper functions, and returns result items to Ulauncher for display and action.
- The extension is therefore a thin orchestration layer rather than the place where search/date logic lives.
4. Command and feature model
- The README shows four user-facing keywords:
- on: open a note by filename
- of: full-content search across notes
- od: open the daily note
- oc: capture text into a note
- These are the primary functional boundaries and likely map to distinct branches in the query-handling flow.
5. Filesystem interaction layer
- The vault is treated as a directory tree of Markdown files.
- The extension must scan note paths, read note contents for search, and create or append to note files for capture.
- The included test-vault/ mirrors a real Obsidian vault structure and acts as the local integration fixture.
6. Search and note-discovery utilities
- src/functions.py is the core helper module for vault-related operations.
- Based on the README and file naming, this module likely contains:
- note discovery / directory traversal
- filename matching
- content search
- file read/write helpers
- The README says this module is covered by doctests, so it appears to hold a lot of the deterministic logic.
7. Result presentation layer
- src/items.py likely defines the structures used to turn search/open actions into Ulauncher result items.
- This is the boundary between raw filesystem matches and the launcher UI:
- title/subtitle formatting
- action handlers for opening notes
- possibly capture/open shortcuts
- In architecture terms, this is the “view model” layer for launcher results.
8. Date and daily-note logic
- src/moment.py is a dedicated utility module for time/date formatting.
- Its presence strongly suggests daily note naming/path generation is isolated from the rest of the logic.
- This separation matters because the daily-note command depends on consistent date conventions independent of vault scanning.
9. Development and compatibility metadata
- manifest.json defines the extension for Ulauncher.
- versions.json is typically used to declare supported extension versions or compatibility data.
- run_dev.sh and run_dev_extension.sh indicate a local development workflow for testing the extension outside normal packaging.
10. Test and fixture boundary
- test-vault/ is a real-looking sample vault with nested folders and note files.
- It provides a concrete filesystem fixture for exercising:
- note lookup by filename
- recursive searches
- subdirectory handling
- daily-note behavior in a realistic vault layout
- The .obsidian/ files show the repo is designed to interoperate with actual Obsidian vault conventions.
11. External dependencies and integration points
- The main external runtime is Ulauncher.
- The target data source is Obsidian content stored locally as Markdown files.
- The README references time_machine for tests, which suggests date-sensitive logic in moment.py.
12. How data flows through the system
- User types a keyword in Ulauncher → main.py routes to the matching feature → helpers in src/functions.py and src/moment.py locate or compute the target note → src/items.py packages matches into launcher results → Ulauncher triggers open/capture actions against the local vault files.
Main entry points: main.py main.py · test-vault test-vault · items.py items.py · Test.md Markdown notes
Components 19
Extension runtime
Ulauncher entrypoint and result assembly
- main.py · Receives launcher keywords, routes commands, and orchestrates vault actions.
main.py - items.py · Formats matches and actions into Ulauncher result items.
src/items.py - Open note · Matches notes by filename and opens the selected note.
- Search notes · Performs full-content search across markdown files.
- Daily note · Computes and opens today's daily note.
- Quick capture · Appends captured text into a target note.
- Result items · Represents the Ulauncher items shown to the user.
Core helpers
Vault scanning, search, and date logic
- functions.py · Core filesystem logic for discovering notes, searching content, and reading or writing markdown files.
src/functions.py - moment.py · Encapsulates date and daily-note naming logic.
src/moment.py - Vault scan · Walks the Obsidian vault directory to discover note paths.
- Name match · Finds notes by filename or partial filename.
- Content search · Searches note bodies for matching text.
- File I/O · Reads note contents and writes or appends capture text.
- Daily compute · Derives the current daily-note filename or path from the active date.
Local fixtures
Sample vault and Obsidian config used for development and testing
- test-vault · Sample Obsidian vault used to exercise lookup, search, and capture behavior.
test-vault - .obsidian · Obsidian plugin and workspace metadata stored alongside notes.
test-vault/.obsidian - Markdown notes · Representative notes in nested folders for recursive discovery and matching.
test-vault/Test.md
Extension metadata
Packaging and compatibility files
- manifest.json · Ulauncher extension metadata and entry configuration.
manifest.json - versions.json · Declared compatibility or version mapping for the extension.
versions.json
Connections 21
- main.py → Open note: routes · Dispatches the open-by-name keyword.
- main.py → Search notes: routes · Dispatches the full-content search keyword.
- main.py → Daily note: routes · Dispatches the daily-note keyword.
- main.py → Quick capture: routes · Dispatches the quick-capture keyword.
- Open note → Name match: uses · Finds candidate notes by name.
- Search notes → Content search: uses · Searches note contents for matches.
- Daily note → Daily compute: uses · Computes today's daily note path.
- Quick capture → File I/O: uses · Writes or appends captured text.
- Name match → Vault scan: depends on · Requires recursive discovery of vault files.
- Content search → Vault scan: depends on · Traverses the vault to inspect markdown files.
- Content search → File I/O: reads · Reads note bodies during search.
- Daily compute → File I/O: coordinates · Targets the daily note file for opening or creation.
- main.py → items.py: builds · Creates launcher-visible items from helper outputs.
- items.py → Result items: formats · Converts matches into Ulauncher result objects.
- Result items → main.py: returns · Handed back to the extension runtime for display.
- test-vault → .obsidian: contains · Sample vault includes Obsidian configuration.
- test-vault → Markdown notes: contains · Sample vault includes representative markdown notes.
- Markdown notes → Vault scan: exercises · Fixture notes validate traversal and matching.
- test-vault → Content search: exercises · Fixture vault supports realistic search behavior.
- manifest.json → main.py: declares · Points Ulauncher at the extension entrypoint.
- versions.json → manifest.json: supports · Provides version compatibility metadata.