mdbasequery is an Obsidian Bases-compatible query engine for Markdown vaults.
It ships as:
- a CLI (
mdbasequery) for scripts and terminal workflows, - a TypeScript library for embedding query execution in applications.
Supported runtimes: Node.js 20+, Bun, and Deno 2.x.
You can run the CLI without installing globally:
npx mdbasequery --help
bunx mdbasequery --helpOr install globally:
npm install -g mdbasequery
# then
mdbasequery --helpCommand form:
mdbasequery [options]There is one command surface; all behavior is controlled through options.
mdbasequery supports three ways to provide the query definition:
.basefile via--base <path>- Inline YAML via
--yaml <yaml-text> - Flag-built query mode (
--filter,--select,--sort, etc.)
If --base/--yaml are not provided, the query is built from flags.
Run a .base file against a vault:
mdbasequery \
--base ./fixtures/queries/basic.base \
--dir ./fixtures/vaults/basic \
--format jsonUse inline YAML (heredoc to avoid shell escaping issues):
QUERY_YAML=$(cat <<'EOF'
views:
- type: table
name: default
filters: score >= 7
properties:
- title
- score
EOF
)
mdbasequery --yaml "$QUERY_YAML" --dir ./fixtures/vaults/basic --format mdUse CLI flags instead of YAML:
mdbasequery \
--dir ./fixtures/vaults/basic \
--filter "score >= 7" \
--select title \
--select score \
--sort score:desc \
--format csvSelect a specific view from a .base file and write output to disk:
mdbasequery \
--base ./fixtures/queries/grouped.base \
--view grouped \
--dir ./fixtures/vaults/basic \
--format yaml \
--out ./result.yamlDisable strict symbol/function checking:
mdbasequery --yaml "views: [{ type: table, name: default }]" --no-strict| Option | Type | Description |
|---|---|---|
--dir <path> |
string | Target directory to scan (default: current directory). |
--base <path> |
string | Path to Obsidian-style .base YAML file. |
--yaml <yaml-text> |
string | Inline YAML text. |
--view <name> |
string | View name to run (default: first view). |
| `--format <json | jsonl | yaml |
--out <path> |
string | Write serialized output to file instead of stdout. |
--strict |
flag | Enable strict mode (default behavior). |
--no-strict |
flag | Disable strict mode for unknown symbols/functions. |
--include <glob> |
repeatable string | Include path glob(s), matched against vault-relative paths. |
--exclude <glob> |
repeatable string | Exclude path glob(s), matched against vault-relative paths. |
--debug |
flag | Enable debug diagnostics in result metadata. |
--filter <expr> |
repeatable string | Add filter expression(s) in flag-built mode. |
--select <property> |
repeatable string | Select/project property/column in flag-built mode. |
| `--sort <prop:asc | desc>` | repeatable string |
--group-by <property> |
string | Group rows by one property in flag-built mode. |
--limit <n> |
number | Limit row count in flag-built mode. |
--help, -h |
flag | Show CLI help text. |
json: one structured object with rows, columns, summaries, stats, diagnostics.jsonl: one JSON object per row.yaml: YAML representation of the full result object.csv: projected columns in declared/selected order.md: Markdown table for quick human review.
- Exit code
0: successful query execution. - Exit code
1: fatal CLI/query error, or row-level diagnostics recorded as errors.
Diagnostics are returned as part of result metadata (and included in structured formats).
- Filters and formulas share the same expression language.
- Effective filter per view is
global filter AND view filter. - Formula dependencies are topologically ordered; cycles fail clearly.
- Strict mode is enabled by default.
- Summary formulas evaluate with
valuesbound to selected column values. - Output ordering is deterministic.
thiscontext in CLI/library mode is deterministic metadata (filePath,name).
npm install mdbasequery
# or
bun add mdbasequeryimport { queryBase, serializeResult } from "mdbasequery";
const result = await queryBase({
dir: "./fixtures/vaults/basic",
yaml: `
views:
- type: table
name: default
filters: score >= 7
properties:
- title
- score
`.trim(),
strict: true,
});
console.log(result.rows.length);
console.log(serializeResult(result, "json"));Primary exports:
queryBase(options): Promise<QueryResult>parseBaseYaml(input): QuerySpeccompileQuery(spec, options?): CompiledQueryrunCompiledQuery(compiled, source?): Promise<QueryResult>serializeResult(result, format): string
Runtime adapters:
detectRuntimeAdapter()nodeAdapter,bunAdapter,denoAdapter
queryBase accepts a QueryBaseOptions object with:
spec?: QuerySpec- already parsed query spec.basePath?: string- path to.basefile.yaml?: string- inline YAML text.view?: string- selected view name.dir?: string- vault root directory.strict?: boolean- strict symbol/function behavior (default true).include?: string[]- include globs.exclude?: string[]- exclude globs.debug?: boolean- enable debug diagnostics.adapter?: RuntimeAdapter- runtime adapter injection.
Provide exactly one query source among spec, basePath, or yaml.
import { compileQuery, parseBaseYaml, runCompiledQuery } from "mdbasequery";
const spec = parseBaseYaml(`
views:
- type: table
name: default
filters: score >= 7
`.trim());
const compiled = compileQuery(spec, { strict: true });
const first = await runCompiledQuery(compiled, { dir: "./vault-a" });
const second = await runCompiledQuery(compiled, { dir: "./vault-b" });
console.log(first.rows.length, second.rows.length);QueryResult contains:
rows: row contexts withnote,file,formula,this, andprojectedfields.columns: projected column order.groups?: grouped rows when grouping is active.summaries?: computed summary values.stats: scan/match timing and counts.diagnostics: warnings and errors.
- Schema/YAML issues throw validation errors (for example from
parseBaseYaml). - Strict mode rejects unknown identifiers/functions.
- Formula cycles throw explicit cycle errors.
- CLI returns exit code
1for failures and diagnostic errors.
- Bun (primary dev runtime)
- Node.js 20+
- Deno 2.x
bun installbun run build
bun run lint-typecheck
bun run test:bun
bun run test:node
bun run test:deno
bun run cibun run ci runs the required local validation suite:
- typecheck/lint
- Bun tests
- Node conformance tests
- Deno conformance tests
GitHub Actions runs:
lint-typechecktest-buntest-nodetest-denocompat-smoke-cli(matrix across Bun/Node/Deno)
src/core- schema, expression engine, query engine, serialization, indexing.src/runtime-adapters- runtime-specific filesystem/path adapters.src/cli.ts- CLI entrypoint.tests- Bun test suite (unit/integration/docs smoke).test-runtime- Node/Deno conformance tests.fixtures- vault and query fixtures..github/workflows/ci.yml- CI workflow definitions.
- Ensure
bun run cipasses locally. - Ensure GitHub Actions checks are green.
- Build artifacts (
dist) and package metadata are correct. - Publish to npm.
- Verify
npx mdbasequery --helpandbunx mdbasequery --helppost-release.