enquire-mcp API reference - v4.0.0-rc.7
    Preparing search index...

    Class Vault

    Vault — the central read-and-cache layer over the user's Obsidian directory. Handles path safety (no escapes via .. or symlinks), intrinsic hidden/reserved path policy plus user privacy filtering (--read-paths allowlist + --exclude-glob denylist), parsed-note caching (in-memory LRU + optional persistent JSON file), and write gating (opt-in via --enable-write).

    Construct once at server start, then share across all tool calls. Methods are async because filesystem IO; the in-memory cache makes repeated reads of the same note ~free.

    Configured vault root.

    Optional visibility, mutation, size, and persistence settings.

    If opts.cacheFile is outside the exact parse-cache namespace.

    If supplied visibility patterns are empty after normalization.

    const vault = new Vault("/home/me/Vault", { enableWrite: false });
    await vault.ensureExists();
    const md = await vault.listMarkdown();
    const note = await vault.readNote(md[0].absPath);
    Index
    excludeGlobs: readonly string[]
    maxCacheEntries: number
    maxDiskCacheBytes: number
    maxFileBytes: number
    persistentCacheEnabled: boolean
    readPaths: readonly string[]
    root: string
    writeEnabled: boolean
    • get cacheFile(): string | null

      Exact .json path of the configured persistent cache, or null before default resolution.

      Returns string | null

    • set cacheFile(file: string | null): void

      Retarget future cache operations to an exact admitted path.

      Parameters

      • file: string | null

        Exact .json main outside reserved feedback/HNSW-meta subclasses, or null.

      Returns void

      If a non-null path is outside the exact parse-cache namespace.

    • Append text to an existing note. Requires enableWrite: true. Refuses if the resulting file would exceed the size cap.

      v3.11.7-rc.2 — opens without O_CREAT, so append can never turn a missing path into a new file, and serializes the descriptor size-check + write by physical file identity across all Vault instances in this process. O_APPEND makes placement atomic; the dev+ino queue also coordinates distinct hardlink paths for one file. Writers in other processes remain outside the Vault API contract.

      Parameters

      • relOrAbs: string

        Vault-relative or absolute target path.

      • addition: string

        Text to append (UTF-8). Caller is responsible for including any leading newline.

      Returns Promise<
          {
              absPath: string;
              appended_bytes: number;
              mtimeMs: number;
              relPath: string;
          },
      >

      Metadata about the file after the append.

      If the vault is read-only, the target does not exist as a regular in-vault file, is privacy-excluded, changes identity during validation, or the append would exceed maxFileBytes.

    • Admit feedback identities against the same live public-path authority as note and PDF reads. Every input must be a vault-relative path to an existing regular .md or .pdf file; traversal, absolute paths, symlinks escaping the vault, hidden/reserved paths, and configured privacy exclusions reject the entire batch. Returned paths use the filesystem's canonical vault-relative spelling and forward separators.

      Parameters

      • relPaths: readonly string[]

        Candidate paths copied from current search hits.

      Returns Promise<string[]>

      Deduplicated canonical public identities in input order.

      If any candidate is not a current public searchable file.

    • Public alias for canonicalRelForPrivacyCheck. v3.7.16 P1-6 — used by renameNote wrapper in src/tools/write.ts to fail-fast on case-insensitive-FS variants before doing O(N) backlink-rewrite work. The inner renameFile also does this check; this public surface lets orchestrators pre-check without duplicating the realpath logic.

      Parameters

      • abs: string

      Returns Promise<string>

    • Once target admission completes, retire the current in-memory generation synchronously and delete the captured on-disk cache family in publication order. An already-known target has no pre-admission suspension; resolving the default target may await filesystem identity first. Reads and saves accepted after rotation belong to the new generation; a save waits for the disk-erasure barrier before it may publish those newer entries. Async reads or loads accepted before the rotation cannot repopulate the new map. Disk inspection/deletion failures reject the returned promise. Resolves the default cache path through normal initialization when persistence is enabled; otherwise it is a no-op when no cache path exists. Before deletion it retires every own shared handle for the physical family and acquires its exclusive eraser role. A conflicting external lifetime rejects before any cache byte is removed.

      Returns Promise<boolean>

      true if any stable, legacy-temp, or generated cache artifact was removed.

    • Stop admitting disk-cache work, join all accepted loads, saves, and clears, then release every exact historical cache-target lifetime. A failed marker cleanup remains retryable through a later call; no target is re-resolved.

      Returns Promise<void>

      A promise that settles only after all retained persistence markers are gone.

    • Verify the vault root exists, is a directory, and resolve through any symlinks. Idempotent — safe to call before every operation; the underlying state is cached after the first successful call.

      Also (when persistent cache is enabled) loads the on-disk parse cache. The first disk target is canonicalized through a two-level persistence lease; its shared lifetime remains held until closePersistence or an explicit same-family clear retires it.

      Returns Promise<void>

      If the vault root doesn't exist or isn't a directory.

    • v3.7.16 P2-13 — find ALL notes with a given title (basename match). Used by write tools to FAIL LOUDLY when multiple files share a basename instead of silently mutating the first walk-order match.

      Pre-3.7.16, appendToNote({ title: "Daily" }) would mutate Work/Daily.md or Personal/Daily.md depending on directory walk order — a silent-data-corruption footgun. Write surfaces now use this method, fail on .length > 1, and surface the candidate paths to the caller so they can disambiguate by path.

      Parameters

      • title: string

        Title without .md (case-insensitive basename match).

      Returns Promise<FileEntry[]>

      All matching file entries (empty array if no match).

    • Find a markdown note by title (basename without .md, case-insensitive). Returns the first match in walk order — vaults with duplicate titles across folders silently pick one.

      v3.7.16 P2-13 — WRITE callers should use findAllByTitle + fail-on-ambiguity instead of this method (silent first-match selection here is fine for read paths but causes silent data corruption when used as the write-target resolver). The resolveTarget helper in src/tools/write.ts has an opts.strictOnAmbiguousTitle flag for the write/read distinction.

      Parameters

      • title: string

        Note title with or without .md suffix.

      Returns Promise<FileEntry | null>

      The matching file entry, or null if no note matches.

    • Periodic Notes plugin config (.obsidian/daily-notes.json + Periodic Notes plugin's data.json). Lazy-loaded, then cached for the process lifetime. Returns an empty config when no plugin files exist.

      Returns Promise<PeriodicConfig>

    • Drop every entry from the in-memory parse cache. Used after bulk changes (e.g. a full vault rebuild). Does NOT delete the on-disk cache file — call clearDiskCache for that.

      Returns void

    • Drop a single cached note by absolute path. Used by the watcher when one file changes — full-cache clear would be wasteful for a 5k-note vault.

      Parameters

      • absPath: string

      Returns void

    • True when a path is hidden/reserved or rejected by a configured privacy filter.

      Parameters

      • relPath: string

      Returns boolean

    • Walk the vault and return a complete, path-sorted inventory ending with the given extension (e.g. ".canvas", ".pdf"). Honors --exclude-glob + --read-paths and fails if the exact inventory exceeds the hard envelope.

      Parameters

      • ext: string
      • Optionalfolder: string

      Returns Promise<FileEntry[]>

    • Parameters

      • extensions: readonly string[]
      • maxFiles: number
      • maxVisitedEntries: number
      • Optionalfolder: string

      Returns Promise<BoundedFileListing>

    • List every markdown file under the vault root (or a subfolder). Skips every hidden or reserved segment recognized by the central vault path policy and refuses to traverse symlinks. Applies the privacy filter (--exclude-glob / --read-paths) before returning.

      Parameters

      • Optionalfolder: string

        Optional vault-relative subfolder. When set, scan only under that folder. Returns [] if the folder doesn't exist, is a symlink, or is itself excluded.

      Returns Promise<FileEntry[]>

      Complete discovered inventory sorted by vault-relative path.

      If the exact inventory exceeds the hard file/traversal envelope or a subtree cannot be inspected completely.

    • One ordered page of admitted notes, resumable after a previous page.

      Complements listFilesByExtensionsBounded, which answers "the whole inventory or nothing" and is what every existing caller wants. A PAGE needs no completeness receipt and no total, so this walk stops as soon as it has one entry more than the page (that extra entry is the "is there more?" answer and is not returned), prunes whole subtrees that sort at or below the resume point, and treats an unreadable directory as skipped rather than fatal. Cost is therefore proportional to the page, not to the vault — which is what lets a vault of any size be enumerated at all.

      Ordering is globally ascending relPath, achieved by ordering each directory's own entries with noteWalkOrderKey; the result is identical to sorting a complete listing, which a differential test pins.

      Privacy, symlink, restricted-path, containment and depth rules are the same as the exhaustive walk: an excluded note is filtered before it is counted.

      Parameters

      • extensions: readonly string[]

        Lower-case extensions to admit, each beginning with ..

      • limit: number

        Maximum entries to return; must be a positive safe integer.

      • Optionalafter: string

        Exclusive relPath resume point, or undefined to start.

      Returns Promise<NotePageListing>

      The page and whether a further admitted note exists after it.

      If limit or extensions are malformed.

      const page = await vault.listNotePage([".md"], 500);
      const next = page.hasMore ? await vault.listNotePage([".md"], 500, page.entries.at(-1)?.relPath) : null;
    • Parameters

      • relOrAbs: string

      Returns Promise<Buffer<ArrayBufferLike>>

    • Read a text file (UTF-8) from the vault. Same path-safety and size cap as readNote, but doesn't parse — useful for non-markdown text files where the caller wants the raw bytes.

      Parameters

      • relOrAbs: string

        Vault-relative or absolute path.

      Returns Promise<string>

      File content as UTF-8 string.

      If the path escapes the vault, is excluded by privacy filter, or the file exceeds the size cap.

    • Read and parse a markdown note. Returns the cached entry when the file's full filesystem receipt hasn't changed; otherwise reads from disk, parses via parseNote, and caches the result (LRU-evicting the oldest entry when at capacity).

      Parameters

      • relOrAbs: string

        Vault-relative or absolute path to a .md file.

      • OptionalknownMtimeMs: number

        Optional pre-listing mtime hint retained for API compatibility. Cache admission always checks a fresh full receipt.

      Returns Promise<CachedNote>

      A detached note snapshot including parsed structure. Mutating the returned object cannot alter the Vault's internal cache generation.

      If the path escapes the vault, is excluded, or exceeds the size cap.

    • Read and parse one markdown generation without consulting or mutating the shared parsed-note cache.

      This is intended for multi-stage callers that must not publish a candidate into separately visible cache state before their own final receipt commits. It performs the same path, size, and before/after source-receipt checks as readNote and returns the same detached public shape.

      Parameters

      • relOrAbs: string

        Vault-relative or absolute path to a .md file.

      • OptionalknownMtimeMs: number

        Optional finite listing hint retained for parity with readNote; authority always comes from a fresh full receipt.

      Returns Promise<CachedNote>

      A detached parsed note that was never inserted into the Vault cache.

    • Rename a markdown file inside the vault.

      A move to a classified-missing destination uses link + unlink, with an exclusive-copy cross-device fallback, regardless of overwrite. Thus an unsnapshotted destination appearing in the final check/use gap cannot be replaced. Plain rename is reserved for a supported case-only spelling of the same canonical directory entry, confirmed by exact realpath plus dev + ino, or a classified-distinct destination with overwrite. A distinct hardlink destination fails closed even with overwrite; byte rollback cannot restore link topology. If an exclusive link/copy publishes the destination but source removal then fails, the rejection explicitly reports that both paths may exist.

      For non-identical path requests, the optional planning receipt is reclassified after the final mutation path guards and immediately before the filesystem syscall. It narrows but cannot eliminate an out-of-process check/use or ABA race. Exact-same-path direct calls retain their legacy overwrite/no-op behavior; renameNote rejects that request.

      Parameters

      • fromRel: string

        Existing vault-relative source path.

      • toRel: string

        Requested vault-relative destination path.

      • opts: RenameFileOptions = {}

        Overwrite choice and optional orchestrator planning receipt.

      Returns Promise<{ from: string; mtimeMs: number; to: string }>

      Vault-relative source/destination paths and destination mtime.

      If a path is excluded or unsafe, a distinct destination exists without overwrite, destination identity is unproven or changed, the destination is a distinct hardlink entry, or a two-step move published the destination but could not remove the source.

      await vault.renameFile("Inbox/Draft.md", "Archive/Draft.md");
      
    • Resolve a vault-relative or absolute path to an absolute path, after asserting the result stays inside the vault root. This is the lexical guard; resolveSafePath additionally walks symlinks.

      Parameters

      • p: string

        Path string (relative or absolute).

      Returns string

      Absolute path.

      If the resolved path escapes the vault root.

    • Flush the in-memory parse cache to disk. Serializes into an unpredictable exclusive same-parent sibling, applies mode 0600 and fsyncs its held descriptor before rename publication. The published leaf is never chmod'd; a missing parent is requested via recursive mode-0700 mkdir (subject to a more-restrictive umask), while an existing/custom parent is never path- chmod'd. The parent directory is not fsync'd, so this is atomic leaf replacement rather than a power-loss durability claim.

      No-op when persistent cache wasn't configured or the cache hasn't been modified since the last save (cacheDirty flag). Even a clean-cache call joins any already-accepted clear of the same target and inherits its failure rather than reporting an early false success. Rejects after erasing any older on-disk generation when the admitted snapshot exceeds the configured byte cap; an oversized replacement must never leave stale or newly excluded note bodies behind while reporting success. Every publication acquires a serialized publisher from the target's pinned scopes and writes only the canonical file captured by its shared lifetime.

      Returns Promise<void>

      If validation/publication fails, the snapshot exceeds the configured on-disk byte cap, or eight save requests are already pending.

    • Return an opaque generation receipt for one current public regular file.

      The path is admitted through the same canonical containment, symlink, and privacy checks as reads. The receipt includes physical identity, size, modification time, and metadata-change time; callers compare the complete string and do not depend on its internal encoding.

      Parameters

      • relOrAbs: string

        Vault-relative or accepted absolute file path.

      Returns Promise<FileSourceState>

      Current regular-file generation state.

      If the path is missing, excluded, escapes the vault, or is not a regular file.

      const before = await vault.sourceState("Notes/A.md");
      const after = await vault.sourceState("Notes/A.md");
      if (before.sourceRevision !== after.sourceRevision) throw new Error("changed");
    • Stat a vault file. Same path-safety as the read methods but no size-cap check (callers may want to inspect oversized files' metadata).

      Parameters

      • relOrAbs: string

        Vault-relative or absolute path.

      Returns Promise<{ isFile: boolean; mtimeMs: number; size: number }>

      Modification time, byte size, and whether the target is a regular file.

    • Convert an absolute path under the vault to a vault-relative one (POSIX-separated on all platforms). Does not verify the result stays inside the vault; callers needing that should use resolveInside.

      Parameters

      • abs: string

      Returns string

    • Create or overwrite a markdown note. Requires enableWrite: true at construction. Honors the intrinsic vault visibility policy and configured privacy filters. Refuses to write through symlinks. Auto-creates parent directories.

      v3.7.13 M2 — overwrite=false uses the wx open flag for atomic exclusive create (closes stat-then-write TOCTOU race).

      v3.7.16 P1-6 — privacy filter runs on the canonical-case relative path (resolved via realpath against the nearest existing parent) rather than the lexical user input. Closes the case-insensitive-FS bypass on default macOS HFS+/APFS and Windows NTFS where personal/secret.md and Personal/secret.md resolve to the same physical file but used to bypass --exclude-glob "Personal/**".

      Parameters

      • relPath: string

        Vault-relative target path. .md suffix is added if absent. Must not be empty / . / .md.

      • content: string

        File body (UTF-8). Must be under the size cap.

      • opts: { overwrite?: boolean } = {}
        • Optionaloverwrite?: boolean

          If true, replace an existing file; otherwise throw when the target exists. Default false.

      Returns Promise<{ absPath: string; bytes: number; mtimeMs: number; relPath: string }>

      Metadata about the written file.

      If the vault is read-only, the destination is excluded, the target is a symlink, content exceeds the cap, or the file exists and overwrite is false.