Thank you to @Sherlock290 for the embed fixes in this release, including math rendering in embedded notes.
Minor Changes
New foam.footnotes.enable setting (#1705). Set it to false when another extension, such as Markdown Footnotes or Markdown Extended, already handles footnotes: the preview no longer renders a second, empty footnotes section, and Foam's footnote hover, go-to-definition and highlighting are turned off. The preview picks up the change after a window reload. The HTML export always keeps footnotes.
a4f170e: New FOAM_PREVIOUS_DAILY_NOTE template variable: in a daily note template it expands to the identifier of the most recent daily note that exists before the one being created, skipping gaps like weekends, so [[$FOAM_PREVIOUS_DAILY_NOTE]] links to it and ${FOAM_PREVIOUS_DAILY_NOTE:nothing yet} supplies a fallback for the first daily note. It only works when the daily note path spells out year, month and day in numbers (#1706).
Patch Changes
.git, .hg, .svn, .DS_Store and Thumbs.db are now always excluded from the workspace, whatever foam.files.exclude says. Because foam.files.exclude is a list, setting it to add a pattern of your own used to replace the built-in excludes and pull those paths back in.
Embeds and foam-query content cells show the right part of the note (#1716, #1718):
Whole-note embeds no longer render the note's frontmatter as a horizontal rule followed by a heading
content embeds keep the whole note body: previously they kept only the first section and always dropped its first line
The title removed by content embeds and the foam-query content field is the note's first H1, wherever it sits — also below a comment or badge, and including the underline of a setext (===) heading. A note whose first heading is an H2 keeps it
section[Label] cells no longer leave a setext heading's underline behind
An indented code block right after the frontmatter keeps its indentation
In @foam/core, Section gains a headingRange covering just the heading lines, and stripFrontMatterAndTitle is exported.
Math in an embedded note (![[note]]) and in foam-query body cells now renders with KaTeX, like it does in the note itself, instead of showing the formula source (#1717). This relies on VS Code's built-in Markdown Math extension; with it disabled, embeds render as before.
Exported notes no longer repeat their title or leak frontmatter (#1719). Both the HTML report and foam export to Starlight now drop the note's first H1 when it is the title, including a setext H1 or one below a comment, and keep it when a different frontmatter title replaces it. The Starlight homepage no longer gets two frontmatter blocks, and notes with CRLF line endings or a ... frontmatter closer are handled.
In @foam/core, ExportedNote gains body: the exported markdown without the frontmatter and title heading.
b108125: Correctness and lifecycle fixes from the core model review:
Files whose names differ only by case no longer overwrite each other in the workspace index (silent data loss on case-sensitive filesystems)
The incremental graph now re-resolves links that a newly added note wins by identifier or directory-index priority, staying equivalent to a full rebuild
Rename edits can no longer corrupt files: duplicate definition edits are deduplicated, partially overlapping edits are rejected, and a single unparsable link skips that link instead of aborting the rename
Tag ranges are computed correctly for frontmatter tags that are substrings of other tags and for hashtags on continuation lines of multi-line paragraphs; quoted "tags" frontmatter keys are recognized
Published static-site graph JSON no longer includes raw note frontmatter, only allowlisted presentation keys (color, type)
Uppercase attachment extensions (photo.PNG) are classified like their lowercase counterparts; rapid successive changes to one file can no longer leave stale content in the workspace; disposal no longer leaks FoamTags, resource providers, or graph-webview registrations; one failing feature no longer aborts the whole extension activation
6a645fa: Fixed notes disappearing from the workspace index when their folder is moved or renamed in the Explorer (#1696). The notes were dropped from the Notes Explorer, graph, backlinks, foam-query and wikilink resolution, under both the old and the new path, and only a window reload brought them back. Because the entries were gone, moving the same folder a second time also silently stopped updating any links pointing into it.
A directory rename now migrates the index itself instead of relying on file watcher events that a directory-granularity rename may never produce: the affected notes are re-indexed under their new paths as part of the rename, on every platform. Index migration also no longer depends on the foam.links.sync.enable setting.
Include/exclude matching now evaluates the globs directly rather than looking paths up in a snapshot of the workspace file listing, which could go stale and never recover. Matching is case-insensitive and covers dot-directories, mirroring how workspace.findFiles behaves today, and the VS Code extension and the CLI now share one matcher implementation.
97b82e4: Foam no longer treats VS Code's files.watcherExclude as a reason to skip files when loading the workspace. That setting means "don't spend CPU watching this", not "this is not part of my workspace" — and VS Code already applies it to recursive watchers itself, so honouring it here bought no CPU saving while silently dropping those notes from the index entirely: no backlinks, no placeholders, and no way to get them back short of changing the setting. To keep a folder out of Foam, use foam.files.exclude, which is unchanged. This also brings the extension back in line with @foam/cli, which never applied files.watcherExclude.
e4b3b24: Fixed newly added images not being picked up until the window was reloaded (#1697). Since 0.44.3 the file watcher was scoped to note and attachment extensions, but it read the extension list straight from foam.files.attachmentExtensions — whose default carries no image types, because images are treated as attachments unconditionally. Pasting an image therefore created a file Foam never saw: no hover preview, no embed in the Markdown preview, and no removal from the graph when the image was deleted or renamed. The watcher now derives its extensions from the attachment provider, so the two can no longer disagree.
6ac7ded: isWithinPath now compares Windows drive paths case-insensitively, matching what FoamWorkspace already did for its own root matching. The two helpers answer the same question — "is this path inside that one?" — but only the workspace one allowed for a drive letter whose case differs between VS Code and Node, which is a case the codebase already knew it could not trust.
The exact comparison reached four places: the check that a new note is inside the workspace, getRootUriFor (which picks the root for .foam/trash and for workspace-relative paths), the MCP server's path serialisation, and the export asset filter. On Windows a drive-case mismatch could make each of them decide a path was outside the workspace when it was not.
05b8a96: Note creation is now defined once in @foam/core and shared by the VS Code commands (create note, daily notes), the CLI and the MCP server. The check that a new note stays inside the workspace — including on every retry path proposed while handling an existing file, and after a template has set its own filepath — now lives in a single place.
Behavior changes that come with it:
The VS Code create-note command resolves template content once. Passing FOAM_SELECTED_TEXT as a variable no longer appends the selected text twice.
Foam variables in the content returned by a JavaScript template are resolved in the CLI and MCP server as well, not only in VS Code.
foam note create --dir
A daily-note directory configured as an absolute path outside the workspace is used as such when a daily-note.md template sets no filepath, matching the behavior without a template. It used to be re-rooted inside the workspace.
466ad05: Fixes to note creation and folder renames, found by re-enabling the foam-vscode integration suite:
create-note no longer fails with path.startsWith is not a function when given a URI, and the workspace no longer throws reference.split is not a function when looked up by one. Both accept a URI-like object but narrowed on instanceof URI, which does not hold for a URI that crosses into the extension bundle's inlined copy of @foam/core. The other string | URI narrowings in URI itself now discriminate on the string too
Renaming a folder keeps its notes in the index without a gap: they are re-keyed under the new path as the rename completes, instead of being removed and re-read asynchronously, which briefly left them indexed under neither path
Renaming the same folder twice in a row now updates the wikilinks both times. The files rewritten by the first rename are re-indexed, and the work is registered as a rename participant so it completes before the rename lands rather than racing whatever comes next
A note inside a renamed folder that linked to a sibling by a path-qualified wikilink kept its old link in the index: the rename re-keyed a copy of the note taken before its links were rewritten, so the backlink disappeared until the file was next read. The file on disk was always correct
Deleting a path that is already gone no longer brings down the extension host with an unhandled EntryNotFound rejection, and neither does renaming one
528a091: The "Create daily note template" button now writes the template to the folder configured in foam.templates.folder, instead of always to .foam/templates.
With a custom templates folder the scaffolded file landed where Foam never looks for it, so the "No daily note template found" warning came back every time and the file appeared somewhere the user had not configured.
1042c53: Foam query path and folder fields are now workspace-relative, as documented, instead of exposing the absolute filesystem path. Previously a workspace at C:\Docs (or /home/me/notes) rendered /C:/Docs/test/file.md instead of /test/file.md. The path: filter, the "/regex/" shorthand, and jexl's resource.path now match against the same workspace-relative path, so anchored patterns like path: "^/projects/" behave identically on every OS. (#1698)