Super Smart Random Note

by zakin
5
4
3
2
1
Score: 50/100

Description

Open random notes matched by saved filters written in a familiar search query syntax.

Reviews

No reviews yet.

Stats

0
stars
124
downloads
0
forks
48
days
48
days
48
days
0
total PRs
0
open PRs
0
closed PRs
0
merged PRs
0
total issues
0
open issues
0
closed issues
11
commits

README file from

Github

Super Smart Random Note

Open random notes matched by saved filters, written in (a subset of) Obsidian's own search query syntax.

  • Default command — "Open random note (default)", always available. Query is empty by default, meaning "any note in the vault".
  • Custom commands — define as many named filters as you want in the plugin settings. Each one becomes its own command in the command palette (bindable to a hotkey, launcher plugins, etc.).

Why a reimplementation instead of Obsidian's real search engine?

Obsidian doesn't expose its internal search engine through the public plugin API — there's no documented way to hand it a query string and get back a list of matching files. This plugin ships its own parser/evaluator that follows the same documented operators (see "Supported syntax" below), evaluated directly against each note's content (frontmatter included) plus its tags from the metadata cache. It is a close but not pixel-perfect clone of core search — see "Known differences" below.

Supported syntax

Operator Meaning Example
(bare word) Note content contains the word meeting
"phrase" Note content contains the exact phrase "kickoff meeting"
/regex/ Note content matches the regex (flags allowed, e.g. /foo/i) /\d{4}-\d{2}-\d{2}/
file: Match against the file name file:.png
path: Match against the full file path path:"Journal/2026"
content: Match against the full note content (same as bare word) content:"happy cat"
tag: Note has this tag (nested tags included, e.g. tag:#work matches #work/meeting) tag:#idea
line: At least one line matches line:(mix flour)
section: At least one heading section matches (best-effort split on heading lines) section:(dog cat)
block: At least one paragraph/block matches (best-effort split on blank lines) block:(dog cat)
task: At least one task line (- [ ]/- [x]) matches task:call
task-todo: At least one unchecked task line matches task-todo:call
task-done: At least one checked ([x]) task line matches task-done:call
[key] Frontmatter property key exists and is truthy [status]
[key:value] Frontmatter property key equals value (or contains it, for list properties). Wikilink-valued properties (- "[[Poems]]") match on the link's target/alias text, not the bracket syntax [status:Draft], [types:poems]
[key:v1 OR v2] Property equals any of the given values [status:Draft OR Published]
OR Logical or (must be uppercase, space-separated) meeting OR work
- Exclude (prefix, no space before the term) meeting -work
(space) Implicit AND meeting work
(...) Grouping meeting (work OR personal)
field:(a b) Distributes the field over each grouped term tag:(idea work) → has both #idea and #work

Matching is always case-insensitive, except inside /regex/ literals (add the i flag yourself if you want a case-insensitive regex).

  • No "Match case" toggle — everything but explicit regex is case-insensitive.
  • section: and block: use a simple heuristic (split on heading lines / blank lines) rather than Obsidian's real block/section parser.
  • No fuzzy matching — all text matching is plain substring (or regex).
  • Bare words and content: only look at note content, not the file name — use file:/path: explicitly if you want to match on the name.
  • Reads every markdown file's content on each random-note request (via the cached vault read), so very large vaults may see a brief delay.
  • [key:value] properties are read with a small built-in YAML frontmatter parser (not Obsidian's metadataCache, which updates on a debounce and can briefly miss a property you just added) — it covers scalars, quoted strings, inline lists ([a, b]), and block lists (- item), but not full YAML (no nested maps, multi-line strings, anchors, etc.).
  • An unrecognized word: immediately followed by a space (or the end of the query) — e.g. types: poems — is a query error, not a search: it looks exactly like an attempted property filter but silently splitting it into two unrelated bare-word terms (types: and poems, found anywhere in the file independently) would return a plausible-looking but wrong count. Use [types:poems] for a real property filter, or quote it — "types: poems" — to search that literal text as a phrase. foo:bar (no space) still works as one literal token, e.g. for a URL.

Settings

  • General — "Open notes in" sets the vault-wide default (same tab / new tab / new window) for every command.
  • Commands — one row per command: the always-present "Default" row plus every custom filter you add. Click a row's name (or its gear icon) to edit its query and optionally override where that command opens notes; the search icon previews how many notes currently match; custom rows also get duplicate and delete icons. Type a name at the bottom and hit "Add command" to create a new filter, then edit its query from its row.

Development

npm install
npm run dev    # watch build
npm run build  # type-check + production build
npm run lint   # eslint (typescript-eslint recommended-type-checked)

Copy main.js, manifest.json, and styles.css into <vault>/.obsidian/plugins/super-smart-random-note/ to install manually, or add the repo to BRAT.

The settings tab implements Obsidian's declarative getSettingDefinitions() API (1.13.0+) with the old imperative display() kept as a fallback for older versions — both paths share the same row-rendering code.

Prior art

The command-row-plus-modal editing UX is modeled after obsidian-advanced-random-note. obsidian-lottery was also a reference for the general idea of filtered random-note picking.