# mikebarkmin/ulauncher-obsidian architecture

> Architecture diagram of the GitHub repository mikebarkmin/ulauncher-obsidian, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-17). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/mikebarkmin/ulauncher-obsidian
- Repository: https://github.com/mikebarkmin/ulauncher-obsidian

## Overview

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`](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/main.py) (main.py), [`test-vault`](https://github.com/mikebarkmin/ulauncher-obsidian/tree/main/test-vault) (test-vault), [`src/items.py`](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/src/items.py) (items.py), [`test-vault/Test.md`](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/test-vault/Test.md) (Markdown notes)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Extension runtime"]
  node_main_py["main.py<br/>Ulauncher entrypoint<br/>[main.py]"]
  node_items_py["items.py<br/>result builder<br/>[items.py]"]
  node_on_cmd(("Open note<br/>keyword flow"))
  node_of_cmd(("Search notes<br/>keyword flow"))
  node_od_cmd(("Daily note<br/>keyword flow"))
  node_oc_cmd(("Quick capture<br/>keyword flow"))
  node_result_format["Result items<br/>launcher model"]
end

subgraph group_helpers["Core helpers"]
  node_functions_py["functions.py<br/>vault ops<br/>[functions.py]"]
  node_moment_py["moment.py<br/>date helper<br/>[moment.py]"]
  node_vault_scan["Vault scan<br/>tree traversal"]
  node_filename_match["Name match<br/>lookup logic"]
  node_content_search["Content search<br/>search logic"]
  node_file_io[("File I/O<br/>markdown access")]
  node_daily_compute["Daily compute<br/>date naming"]
end

subgraph group_fixtures["Local fixtures"]
  node_test_vault[("test-vault<br/>sample vault")]
  node_obsidian_cfg[".obsidian<br/>vault config<br/>[.obsidian]"]
  node_test_notes["Markdown notes<br/>fixture notes<br/>[Test.md]"]
end

subgraph group_meta["Extension metadata"]
  node_manifest_json["manifest.json<br/>extension manifest<br/>[manifest.json]"]
  node_versions_json["versions.json<br/>compat metadata<br/>[versions.json]"]
end

node_main_py -->|"routes"| node_on_cmd
node_main_py -->|"routes"| node_of_cmd
node_main_py -->|"routes"| node_od_cmd
node_main_py -->|"routes"| node_oc_cmd
node_on_cmd -->|"uses"| node_filename_match
node_of_cmd -->|"uses"| node_content_search
node_od_cmd -->|"uses"| node_daily_compute
node_oc_cmd -->|"uses"| node_file_io
node_filename_match -->|"depends on"| node_vault_scan
node_content_search -->|"depends on"| node_vault_scan
node_content_search -->|"reads"| node_file_io
node_daily_compute -->|"coordinates"| node_file_io
node_main_py -->|"builds"| node_items_py
node_items_py -->|"formats"| node_result_format
node_result_format -->|"returns"| node_main_py
node_test_vault -->|"contains"| node_obsidian_cfg
node_test_vault -->|"contains"| node_test_notes
node_test_notes -.->|"exercises"| node_vault_scan
node_test_vault -.->|"exercises"| node_content_search
node_manifest_json -->|"declares"| node_main_py
node_versions_json -->|"supports"| node_manifest_json

click node_main_py "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/main.py"
click node_items_py "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/src/items.py"
click node_functions_py "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/src/functions.py"
click node_moment_py "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/src/moment.py"
click node_test_vault "https://github.com/mikebarkmin/ulauncher-obsidian/tree/main/test-vault"
click node_obsidian_cfg "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/test-vault/.obsidian"
click node_test_notes "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/test-vault/Test.md"
click node_manifest_json "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/manifest.json"
click node_versions_json "https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/versions.json"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main_py,node_items_py,node_on_cmd,node_of_cmd,node_od_cmd,node_oc_cmd,node_result_format toneBlue
class node_functions_py,node_moment_py,node_vault_scan,node_filename_match,node_content_search,node_file_io,node_daily_compute toneAmber
class node_test_vault,node_obsidian_cfg,node_test_notes toneMint
class node_manifest_json,node_versions_json toneRose
```

## Components

### Extension runtime

Ulauncher entrypoint and result assembly

- [main.py](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/main.py): Ulauncher entrypoint · Receives launcher keywords, routes commands, and orchestrates vault actions. · `main.py`
- [items.py](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/src/items.py): result builder · Formats matches and actions into Ulauncher result items. · `src/items.py`
- **Open note**: keyword flow · Matches notes by filename and opens the selected note.
- **Search notes**: keyword flow · Performs full-content search across markdown files.
- **Daily note**: keyword flow · Computes and opens today's daily note.
- **Quick capture**: keyword flow · Appends captured text into a target note.
- **Result items**: launcher model · Represents the Ulauncher items shown to the user.

### Core helpers

Vault scanning, search, and date logic

- [functions.py](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/src/functions.py): vault ops · Core filesystem logic for discovering notes, searching content, and reading or writing markdown files. · `src/functions.py`
- [moment.py](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/src/moment.py): date helper · Encapsulates date and daily-note naming logic. · `src/moment.py`
- **Vault scan**: tree traversal · Walks the Obsidian vault directory to discover note paths.
- **Name match**: lookup logic · Finds notes by filename or partial filename.
- **Content search**: search logic · Searches note bodies for matching text.
- **File I/O**: markdown access · Reads note contents and writes or appends capture text.
- **Daily compute**: date naming · 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](https://github.com/mikebarkmin/ulauncher-obsidian/tree/main/test-vault): sample vault · Sample Obsidian vault used to exercise lookup, search, and capture behavior. · `test-vault`
- [.obsidian](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/test-vault/.obsidian): vault config · Obsidian plugin and workspace metadata stored alongside notes. · `test-vault/.obsidian`
- [Markdown notes](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/test-vault/Test.md): fixture notes · Representative notes in nested folders for recursive discovery and matching. · `test-vault/Test.md`

### Extension metadata

Packaging and compatibility files

- [manifest.json](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/manifest.json): extension manifest · Ulauncher extension metadata and entry configuration. · `manifest.json`
- [versions.json](https://github.com/mikebarkmin/ulauncher-obsidian/blob/main/versions.json): compat metadata · Declared compatibility or version mapping for the extension. · `versions.json`

## Connections

- 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.
