# Technical Documentation: foambubble/foam

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/foambubble/foam)

### Index (`docs/index.md`)

# What is Foam?

Foam is a personal knowledge management system built on [Visual Studio Code](https://code.visualstudio.com/) and [GitHub](https://github.com/). It helps you organize research, create discoverable notes, and publish your knowledge.

## Key Features

- **Wikilinks** - Connect thoughts with `[[double bracket]]` syntax
- **Embeds** - Include content from other notes with `![[note]]` syntax
- **Backlinks** - Automatically discover connections between notes
- **Graph visualization** - See your knowledge network visually
- **Daily notes** - Capture timestamped thoughts
- **Templates** - Standardize note creation
- **Tags** - Organize and filter content

## Why Choose Foam?

- **Free and open source** - No subscriptions or vendor lock-in
- **Own your data** - Notes stored as standard Markdown files
- **VS Code integration** - Leverage powerful editing and extensions
- **Git-based** - Version control and collaboration built-in

Foam is like a bathtub: _What you get out of it depends on what you put into it._

<p class="announcement">
  <b>New!</b> Join <a href="https://discord.com/invite/HV2tn2FpEk" target="_blank">Foam community Discord</a> for users and contributors!
</p>

<div class="website-only">
    <a class="github-button" href="https://github.com/foambubble/foam" data-icon="octicon-star" data-size="large" data-show-count="true" aria-label="Star foambubble/foam on GitHub">Star</a>
    <a class="github-button" href="https://github.com/foambubble/foam-template" data-icon="octicon-repo-template" data-size="large" aria-label="Use this template foambubble/foam-template on GitHub">Use this template</a>
</div>

## Table of Contents

- [What is Foam?](#what-is-foam)
  - [Key Features](#key-features)
  - [Why Choose Foam?](#why-choose-foam)
  - [Table of Contents](#table-of-contents)
  - [How do I use Foam?](#how-do-i-use-foam)
  - [What's in a Foam?](#whats-in-a-foam)
  - [Getting started](#getting-started)
  - [Features](#features)
  - [Contributing](#contributing)
  - [Thanks and attribution](#thanks-and-attribution)
  - [License](#license)

## How do I use Foam?

Foam helps you create relationships between thoughts and information through:

1. **Atomic notes** - Write focused markdown documents on single topics
2. **Wikilinks** - Connect ideas with `[[double bracket]]` syntax
3. **Backlinks** - Discover unexpected connections between notes
4. **Graph visualization** - See your knowledge network visually

Success with Foam depends on consistent note-taking and linking habits.

## What's in a Foam?

Foam combines existing tools:

1. **VS Code** - Enhanced with [[recommended-extensions]] optimized for knowledge management
2. **GitHub** - Version control, backup, and collaboration
3. **Static site generators** - Publish to GitHub Pages, Netlify, or Vercel

> This documentation was created using Foam.

## Getting started

**Requirements:** GitHub account and Visual Studio Code

1. **Create repository** - Use the [foam-template](https://github.com/foambubble/foam-template) to generate a new repository

   <a class="github-button" href="https://github.com/foambubble/foam-template/generate" data-icon="octicon-repo-template" data-size="large" aria-label="Use this template foambubble/foam-template on GitHub">Use this template</a>

2. **Clone and open** - Clone locally and open the folder in VS Code
3. **Install extensions** - Click "Install all" when prompted for recommended extensions
4. **Configure** - Edit `.vscode/settings.json` for your preferences

**Next steps:**

- Explore the [[recipes]] for usage patterns
- Check [[frequently-asked-questions]] if you need help
- Report issues on [GitHub](http://github.com/foambubble/foam/issues)

## Features

Foam leverages VS Code and [[recommended-extensions]] to provide:

- **Wikilinks** with autocomplete and navigation
- **Backlinks** panel showing connections
- **Graph visualization** of your knowledge network
- **Daily notes** with templates and snippets
- **Tag system** for organization
- **Publishing** to static sites



Explore [[recipes]] for usage patterns and workflows.

## Contributing

Foam is an evolving project and we welcome contributions:

- Read our [[principles]] to understand Foam's philosophy
- Follow the [[contribution-guide]] to get involved
- Share feedback via [GitHub issues](https://github.com/foambubble/foam/issues)

## Thanks and attribution




<table>
  <tbody>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://jevakallio.dev/"><img src="https://avatars1.githubusercontent.com/u/1203949?v=4?s=60" width="60px;" alt="Jani Eväkallio"/><br /><sub><b>Jani Eväkallio</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jevakallio" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://joeprevite.com/"><img src="https://avatars3.githubusercontent.com/u/3806031?v=4?s=60" width="60px;" alt="Joe Previte"/><br /><sub><b>Joe Previte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jsjoeio" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/riccardoferretti"><img src="https://avatars3.githubusercontent.com/u/457005?v=4?s=60" width="60px;" alt="Riccardo"/><br /><sub><b>Riccardo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=riccardoferretti" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://ojanaho.com/"><img src="https://avatars0.githubusercontent.com/u/2180090?v=4?s=60" width="60px;" alt="Janne Ojanaho"/><br /><sub><b>Janne Ojanaho</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jojanaho" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://bypaulshen.com/"><img src="https://avatars3.githubusercontent.com/u/2266187?v=4?s=60" width="60px;" alt="Paul Shen"/><br /><sub><b>Paul Shen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=paulshen" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/coffenbacher"><img src="https://avatars0.githubusercontent.com/u/245867?v=4?s=60" width="60px;" alt="coffenbacher"/><br /><sub><b>coffenbacher</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=coffenbacher" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://mathieu.dutour.me/"><img src="https://avatars2.githubusercontent.com/u/3254314?v=4?s=60" width="60px;" alt="Mathieu Dutour"/><br /><sub><b>Mathieu Dutour</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=mathieudutour" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/presidentelect"><img src="https://avatars2.githubusercontent.com/u/1242300?v=4?s=60" width="60px;" alt="Michael Hansen"/><br /><sub><b>Michael Hansen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=presidentelect" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://klickverbot.at/"><img src="https://avatars1.githubusercontent.com/u/19335?v=4?s=60" width="60px;" alt="David Nadlinger"/><br /><sub><b>David Nadlinger</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dnadlinger" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://pluckd.co/"><img src="https://avatars2.githubusercontent.com/u/20598571?v=4?s=60" width="60px;" alt="Fernando"/><br /><sub><b>Fernando</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MrCordeiro" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/jfgonzalez7"><img src="https://avatars3.githubusercontent.com/u/58857736?v=4?s=60" width="60px;" alt="Juan Gonzalez"/><br /><sub><b>Juan Gonzalez</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jfgonzalez7" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.louiechristie.com/"><img src="https://avatars1.githubusercontent.com/u/6807448?v=4?s=60" width="60px;" alt="Louie Christie"/><br /><sub><b>Louie Christie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=louiechristie" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://supersandro.de/"><img src="https://avatars2.githubusercontent.com/u/7258858?v=4?s=60" width="60px;" alt="Sandro"/><br /><sub><b>Sandro</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SuperSandro2000" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Skn0tt"><img src="https://avatars1.githubusercontent.com/u/14912729?v=4?s=60" width="60px;" alt="Simon Knott"/><br /><sub><b>Simon Knott</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Skn0tt" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://styfle.dev/"><img src="https://avatars1.githubusercontent.com/u/229881?v=4?s=60" width="60px;" alt="Steven"/><br /><sub><b>Steven</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=styfle" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Georift"><img src="https://avatars2.githubusercontent.com/u/859430?v=4?s=60" width="60px;" alt="Tim"/><br /><sub><b>Tim</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Georift" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/sauravkhdoolia"><img src="https://avatars1.githubusercontent.com/u/34188267?v=4?s=60" width="60px;" alt="Saurav Khdoolia"/><br /><sub><b>Saurav Khdoolia</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sauravkhdoolia" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://anku.netlify.com/"><img src="https://avatars1.githubusercontent.com/u/22813027?v=4?s=60" width="60px;" alt="Ankit Tiwari"/><br /><sub><b>Ankit Tiwari</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anku255" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Tests">⚠️</a> <a href="https://github.com/foambubble/foam/commits?author=anku255" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ayushbaweja"><img src="https://avatars1.githubusercontent.com/u/44344063?v=4?s=60" width="60px;" alt="Ayush Baweja"/><br /><sub><b>Ayush Baweja</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ayushbaweja" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/TaiChi-IO"><img src="https://avatars3.githubusercontent.com/u/65092992?v=4?s=60" width="60px;" alt="TaiChi-IO"/><br /><sub><b>TaiChi-IO</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=TaiChi-IO" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/juanfrank77"><img src="https://avatars1.githubusercontent.com/u/12146882?v=4?s=60" width="60px;" alt="Juan F Gonzalez "/><br /><sub><b>Juan F Gonzalez </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=juanfrank77" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://sanketdg.github.io"><img src="https://avatars3.githubusercontent.com/u/8980971?v=4?s=60" width="60px;" alt="Sanket Dasgupta"/><br /><sub><b>Sanket Dasgupta</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Documentation">📖</a> <a href="https://github.com/foambubble/foam/commits?author=SanketDG" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/nstafie"><img src="https://avatars1.githubusercontent.com/u/10801854?v=4?s=60" width="60px;" alt="Nicholas Stafie"/><br /><sub><b>Nicholas Stafie</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nstafie" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/francishamel"><img src="https://avatars3.githubusercontent.com/u/36383308?v=4?s=60" width="60px;" alt="Francis Hamel"/><br /><sub><b>Francis Hamel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=francishamel" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://digiguru.co.uk"><img src="https://avatars1.githubusercontent.com/u/619436?v=4?s=60" width="60px;" alt="digiguru"/><br /><sub><b>digiguru</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=digiguru" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/chirag-singhal"><img src="https://avatars3.githubusercontent.com/u/42653703?v=4?s=60" width="60px;" alt="CHIRAG SINGHAL"/><br /><sub><b>CHIRAG SINGHAL</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chirag-singhal" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/lostintangent"><img src="https://avatars3.githubusercontent.com/u/116461?v=4?s=60" width="60px;" alt="Jonathan Carter"/><br /><sub><b>Jonathan Carter</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lostintangent" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.synesthesia.co.uk"><img src="https://avatars3.githubusercontent.com/u/181399?v=4?s=60" width="60px;" alt="Julian Elve"/><br /><sub><b>Julian Elve</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=synesthesia" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/thomaskoppelaar"><img src="https://avatars3.githubusercontent.com/u/36331365?v=4?s=60" width="60px;" alt="Thomas Koppelaar"/><br /><sub><b>Thomas Koppelaar</b></sub></a><br /><a href="#question-thomaskoppelaar" title="Answering Questions">💬</a> <a href="https://github.com/foambubble/foam/commits?author=thomaskoppelaar" title="Code">💻</a> <a href="#userTesting-thomaskoppelaar" title="User Testing">📓</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.akshaymehra.com"><img src="https://avatars1.githubusercontent.com/u/8671497?v=4?s=60" width="60px;" alt="Akshay"/><br /><sub><b>Akshay</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MehraAkshay" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://johnlindquist.com"><img src="https://avatars0.githubusercontent.com/u/36073?v=4?s=60" width="60px;" alt="John Lindquist"/><br /><sub><b>John Lindquist</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=johnlindquist" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://ashwin.run/"><img src="https://avatars2.githubusercontent.com/u/1689183?v=4?s=60" width="60px;" alt="Ashwin Ramaswami"/><br /><sub><b>Ashwin Ramaswami</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=epicfaace" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Klaudioz"><img src="https://avatars1.githubusercontent.com/u/632625?v=4?s=60" width="60px;" alt="Claudio Canales"/><br /><sub><b>Claudio Canales</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Klaudioz" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/vitaly-pevgonen"><img src="https://avatars0.githubusercontent.com/u/6272738?v=4?s=60" width="60px;" alt="vitaly-pevgonen"/><br /><sub><b>vitaly-pevgonen</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vitaly-pevgonen" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://dshemetov.github.io"><img src="https://avatars0.githubusercontent.com/u/1810426?v=4?s=60" width="60px;" alt="Dmitry Shemetov"/><br /><sub><b>Dmitry Shemetov</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dshemetov" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/hooncp"><img src="https://avatars1.githubusercontent.com/u/48883554?v=4?s=60" width="60px;" alt="hooncp"/><br /><sub><b>hooncp</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hooncp" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://rt-canada.ca"><img src="https://avatars1.githubusercontent.com/u/13721239?v=4?s=60" width="60px;" alt="Martin Laws"/><br /><sub><b>Martin Laws</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=martinlaws" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://seanksmith.me"><img src="https://avatars3.githubusercontent.com/u/2085441?v=4?s=60" width="60px;" alt="Sean K Smith"/><br /><sub><b>Sean K Smith</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sksmith" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/kevin-neely/"><img src="https://avatars1.githubusercontent.com/u/37545028?v=4?s=60" width="60px;" alt="Kevin Neely"/><br /><sub><b>Kevin Neely</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=kneely" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://ariefrahmansyah.dev"><img src="https://avatars3.githubusercontent.com/u/8122852?v=4?s=60" width="60px;" alt="Arief Rahmansyah"/><br /><sub><b>Arief Rahmansyah</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ariefrahmansyah" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://vhanda.in"><img src="https://avatars2.githubusercontent.com/u/426467?v=4?s=60" width="60px;" alt="Vishesh Handa"/><br /><sub><b>Vishesh Handa</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=vHanda" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.linkedin.com/in/heroichitesh"><img src="https://avatars3.githubusercontent.com/u/37622734?v=4?s=60" width="60px;" alt="Hitesh Kumar"/><br /><sub><b>Hitesh Kumar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=HeroicHitesh" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://spencerwoo.com"><img src="https://avatars2.githubusercontent.com/u/32114380?v=4?s=60" width="60px;" alt="Spencer Woo"/><br /><sub><b>Spencer Woo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=spencerwooo" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://ingalless.com"><img src="https://avatars3.githubusercontent.com/u/22981941?v=4?s=60" width="60px;" alt="ingalless"/><br /><sub><b>ingalless</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=ingalless" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://jmg-duarte.github.io"><img src="https://avatars2.githubusercontent.com/u/15343819?v=4?s=60" width="60px;" alt="José Duarte"/><br /><sub><b>José Duarte</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Code">💻</a> <a href="https://github.com/foambubble/foam/commits?author=jmg-duarte" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.yenly.wtf"><img src="https://avatars1.githubusercontent.com/u/6759658?v=4?s=60" width="60px;" alt="Yenly"/><br /><sub><b>Yenly</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=yenly" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.hikerpig.cn"><img src="https://avatars1.githubusercontent.com/u/2259688?v=4?s=60" width="60px;" alt="hikerpig"/><br /><sub><b>hikerpig</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hikerpig" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://sigfried.org"><img src="https://avatars1.githubusercontent.com/u/1586931?v=4?s=60" width="60px;" alt="Sigfried Gold"/><br /><sub><b>Sigfried Gold</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Sigfried" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.tristansokol.com"><img src="https://avatars3.githubusercontent.com/u/867661?v=4?s=60" width="60px;" alt="Tristan Sokol"/><br /><sub><b>Tristan Sokol</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tristansokol" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://umbrellait.com"><img src="https://avatars0.githubusercontent.com/u/49779373?v=4?s=60" width="60px;" alt="Danil Rodin"/><br /><sub><b>Danil Rodin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=umbrellait-danil-rodin" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/scottjoewilliams/"><img src="https://avatars1.githubusercontent.com/u/2026866?v=4?s=60" width="60px;" alt="Scott Williams"/><br /><sub><b>Scott Williams</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=scott-joe" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://jackiexiao.github.io/blog"><img src="https://avatars2.githubusercontent.com/u/18050469?v=4?s=60" width="60px;" alt="jackiexiao"/><br /><sub><b>jackiexiao</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Jackiexiao" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://generativist.substack.com/"><img src="https://avatars3.githubusercontent.com/u/78835?v=4?s=60" width="60px;" alt="John B Nelson"/><br /><sub><b>John B Nelson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jbn" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/asifm"><img src="https://avatars2.githubusercontent.com/u/3958387?v=4?s=60" width="60px;" alt="Asif Mehedi"/><br /><sub><b>Asif Mehedi</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=asifm" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/litanlitudan"><img src="https://avatars2.githubusercontent.com/u/4970420?v=4?s=60" width="60px;" alt="Tan Li"/><br /><sub><b>Tan Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=litanlitudan" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://shaunagordon.com"><img src="https://avatars1.githubusercontent.com/u/579361?v=4?s=60" width="60px;" alt="Shauna Gordon"/><br /><sub><b>Shauna Gordon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ShaunaGordon" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://mcluck.tech"><img src="https://avatars1.githubusercontent.com/u/1753801?v=4?s=60" width="60px;" alt="Mike Cluck"/><br /><sub><b>Mike Cluck</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MCluck90" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://brandonpugh.com"><img src="https://avatars1.githubusercontent.com/u/684781?v=4?s=60" width="60px;" alt="Brandon Pugh"/><br /><sub><b>Brandon Pugh</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bpugh" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://max.davitt.me"><img src="https://avatars1.githubusercontent.com/u/27709025?v=4?s=60" width="60px;" alt="Max Davitt"/><br /><sub><b>Max Davitt</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=themaxdavitt" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://briananglin.me"><img src="https://avatars3.githubusercontent.com/u/2637602?v=4?s=60" width="60px;" alt="Brian Anglin"/><br /><sub><b>Brian Anglin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=anglinb" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://deft.work"><img src="https://avatars1.githubusercontent.com/u/1455507?v=4?s=60" width="60px;" alt="elswork"/><br /><sub><b>elswork</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=elswork" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://leonh.fr/"><img src="https://avatars.githubusercontent.com/u/19996318?v=4?s=60" width="60px;" alt="léon h"/><br /><sub><b>léon h</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=leonhfr" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://nygaard.site"><img src="https://avatars.githubusercontent.com/u/4606342?v=4?s=60" width="60px;" alt="Nikhil Nygaard"/><br /><sub><b>Nikhil Nygaard</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=njnygaard" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://www.nitwit.se"><img src="https://avatars.githubusercontent.com/u/1382124?v=4?s=60" width="60px;" alt="Mark Dixon"/><br /><sub><b>Mark Dixon</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nitwit-se" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/joeltjames"><img src="https://avatars.githubusercontent.com/u/3732400?v=4?s=60" width="60px;" alt="Joel James"/><br /><sub><b>Joel James</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joeltjames" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.ryo33.com"><img src="https://avatars.githubusercontent.com/u/8780513?v=4?s=60" width="60px;" alt="Hashiguchi Ryo"/><br /><sub><b>Hashiguchi Ryo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ryo33" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://movermeyer.com"><img src="https://avatars.githubusercontent.com/u/1459385?v=4?s=60" width="60px;" alt="Michael Overmeyer"/><br /><sub><b>Michael Overmeyer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=movermeyer" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/derrickqin"><img src="https://avatars.githubusercontent.com/u/3038111?v=4?s=60" width="60px;" alt="Derrick Qin"/><br /><sub><b>Derrick Qin</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=derrickqin" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/zomars/"><img src="https://avatars.githubusercontent.com/u/3504472?v=4?s=60" width="60px;" alt="Omar López"/><br /><sub><b>Omar López</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=zomars" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://robincn.com"><img src="https://avatars.githubusercontent.com/u/1583193?v=4?s=60" width="60px;" alt="Robin King"/><br /><sub><b>Robin King</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=RobinKing" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://twitter.com/deegovee"><img src="https://avatars.githubusercontent.com/u/4730170?v=4?s=60" width="60px;" alt="Dheepak "/><br /><sub><b>Dheepak </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dheepakg" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/daniel-vera-g"><img src="https://avatars.githubusercontent.com/u/28257108?v=4?s=60" width="60px;" alt="Daniel VG"/><br /><sub><b>Daniel VG</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=daniel-vera-g" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Barabazs"><img src="https://avatars.githubusercontent.com/u/31799121?v=4?s=60" width="60px;" alt="Barabas"/><br /><sub><b>Barabas</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Barabazs" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://enginveske@gmail.com"><img src="https://avatars.githubusercontent.com/u/43685404?v=4?s=60" width="60px;" alt="Engincan VESKE"/><br /><sub><b>Engincan VESKE</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=EngincanV" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.paulderaaij.nl"><img src="https://avatars.githubusercontent.com/u/495374?v=4?s=60" width="60px;" alt="Paul de Raaij"/><br /><sub><b>Paul de Raaij</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=pderaaij" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/bronson"><img src="https://avatars.githubusercontent.com/u/1776?v=4?s=60" width="60px;" alt="Scott Bronson"/><br /><sub><b>Scott Bronson</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bronson" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://rafaelriedel.de"><img src="https://avatars.githubusercontent.com/u/41793?v=4?s=60" width="60px;" alt="Rafael Riedel"/><br /><sub><b>Rafael Riedel</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=rafo" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Pearcekieser"><img src="https://avatars.githubusercontent.com/u/5055971?v=4?s=60" width="60px;" alt="Pearcekieser"/><br /><sub><b>Pearcekieser</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Pearcekieser" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/theowenyoung"><img src="https://avatars.githubusercontent.com/u/62473795?v=4?s=60" width="60px;" alt="Owen Young"/><br /><sub><b>Owen Young</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=theowenyoung" title="Documentation">📖</a> <a href="#content-theowenyoung" title="Content">🖋</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.prashu.com"><img src="https://avatars.githubusercontent.com/u/476729?v=4?s=60" width="60px;" alt="Prashanth Subrahmanyam"/><br /><sub><b>Prashanth Subrahmanyam</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ksprashu" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/JonasSprenger"><img src="https://avatars.githubusercontent.com/u/25108895?v=4?s=60" width="60px;" alt="Jonas SPRENGER"/><br /><sub><b>Jonas SPRENGER</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=JonasSprenger" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Laptop765"><img src="https://avatars.githubusercontent.com/u/1468359?v=4?s=60" width="60px;" alt="Paul"/><br /><sub><b>Paul</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Laptop765" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://bandism.net/"><img src="https://avatars.githubusercontent.com/u/22633385?v=4?s=60" width="60px;" alt="Ikko Ashimine"/><br /><sub><b>Ikko Ashimine</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=eltociear" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/memeplex"><img src="https://avatars.githubusercontent.com/u/2845433?v=4?s=60" width="60px;" alt="memeplex"/><br /><sub><b>memeplex</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=memeplex" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/AndreiD049"><img src="https://avatars.githubusercontent.com/u/52671223?v=4?s=60" width="60px;" alt="AndreiD049"/><br /><sub><b>AndreiD049</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=AndreiD049" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/iam-yan"><img src="https://avatars.githubusercontent.com/u/48427014?v=4?s=60" width="60px;" alt="Yan"/><br /><sub><b>Yan</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=iam-yan" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://WikiEducator.org/User:JimTittsler"><img src="https://avatars.githubusercontent.com/u/180326?v=4?s=60" width="60px;" alt="Jim Tittsler"/><br /><sub><b>Jim Tittsler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jimt" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://malcolmmielle.wordpress.com/"><img src="https://avatars.githubusercontent.com/u/4457840?v=4?s=60" width="60px;" alt="Malcolm Mielle"/><br /><sub><b>Malcolm Mielle</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MalcolmMielle" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://snippets.page/"><img src="https://avatars.githubusercontent.com/u/74916913?v=4?s=60" width="60px;" alt="Veesar"/><br /><sub><b>Veesar</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=veesar" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/bentongxyz"><img src="https://avatars.githubusercontent.com/u/60358804?v=4?s=60" width="60px;" alt="bentongxyz"/><br /><sub><b>bentongxyz</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=bentongxyz" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://brianjdevries.com"><img src="https://avatars.githubusercontent.com/u/42778030?v=4?s=60" width="60px;" alt="Brian DeVries"/><br /><sub><b>Brian DeVries</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=techCarpenter" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://Cliffordfajardo.com"><img src="https://avatars.githubusercontent.com/u/6743796?v=4?s=60" width="60px;" alt="Clifford Fajardo "/><br /><sub><b>Clifford Fajardo </b></sub></a><br /><a href="#tool-cliffordfajardo" title="Tools">🔧</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://cu-dev.ca"><img src="https://avatars.githubusercontent.com/u/6589365?v=4?s=60" width="60px;" alt="Chris Usick"/><br /><sub><b>Chris Usick</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=chrisUsick" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/josephdecock"><img src="https://avatars.githubusercontent.com/u/1145533?v=4?s=60" width="60px;" alt="Joe DeCock"/><br /><sub><b>Joe DeCock</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=josephdecock" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.drewtyler.com"><img src="https://avatars.githubusercontent.com/u/5640816?v=4?s=60" width="60px;" alt="Drew Tyler"/><br /><sub><b>Drew Tyler</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=drewtyler" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Lauviah0622"><img src="https://avatars.githubusercontent.com/u/43416399?v=4?s=60" width="60px;" alt="Lauviah0622"/><br /><sub><b>Lauviah0622</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Lauviah0622" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.elastic.co/elastic-agent"><img src="https://avatars.githubusercontent.com/u/1813008?v=4?s=60" width="60px;" alt="Josh Dover"/><br /><sub><b>Josh Dover</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=joshdover" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://phelm.co.uk"><img src="https://avatars.githubusercontent.com/u/4057948?v=4?s=60" width="60px;" alt="Phil Helm"/><br /><sub><b>Phil Helm</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=phelma" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/lingyv-li"><img src="https://avatars.githubusercontent.com/u/8937944?v=4?s=60" width="60px;" alt="Larry Li"/><br /><sub><b>Larry Li</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=lingyv-li" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/infogulch"><img src="https://avatars.githubusercontent.com/u/133882?v=4?s=60" width="60px;" alt="Joe Taber"/><br /><sub><b>Joe Taber</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=infogulch" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://www.readingsnail.pe.kr"><img src="https://avatars.githubusercontent.com/u/1904967?v=4?s=60" width="60px;" alt="Woosuk Park"/><br /><sub><b>Woosuk Park</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=readingsnail" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.dmurph.com"><img src="https://avatars.githubusercontent.com/u/294026?v=4?s=60" width="60px;" alt="Daniel Murphy"/><br /><sub><b>Daniel Murphy</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dmurph" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Dominic-DallOsto"><img src="https://avatars.githubusercontent.com/u/26859884?v=4?s=60" width="60px;" alt="Dominic D"/><br /><sub><b>Dominic D</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Dominic-DallOsto" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://elgirafo.xyz"><img src="https://avatars.githubusercontent.com/u/80516439?v=4?s=60" width="60px;" alt="luca"/><br /><sub><b>luca</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=elgirafo" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Lloyd-Jackman-UKPL"><img src="https://avatars.githubusercontent.com/u/55206370?v=4?s=60" width="60px;" alt="Lloyd Jackman"/><br /><sub><b>Lloyd Jackman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Lloyd-Jackman-UKPL" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://sn3akiwhizper.github.io"><img src="https://avatars.githubusercontent.com/u/102705294?v=4?s=60" width="60px;" alt="sn3akiwhizper"/><br /><sub><b>sn3akiwhizper</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=sn3akiwhizper" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://jonathanpberger.com/"><img src="https://avatars.githubusercontent.com/u/41085?v=4?s=60" width="60px;" alt="jonathan berger"/><br /><sub><b>jonathan berger</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jonathanpberger" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/badsketch"><img src="https://avatars.githubusercontent.com/u/8953212?v=4?s=60" width="60px;" alt="Daniel Wang"/><br /><sub><b>Daniel Wang</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=badsketch" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://yongliangliu.com"><img src="https://avatars.githubusercontent.com/u/41845017?v=4?s=60" width="60px;" alt="Liu YongLiang"/><br /><sub><b>Liu YongLiang</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tlylt" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://scottakerman.com"><img src="https://avatars.githubusercontent.com/u/15224439?v=4?s=60" width="60px;" alt="Scott Akerman"/><br /><sub><b>Scott Akerman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Skakerman" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://www.jim-graham.net/"><img src="https://avatars.githubusercontent.com/u/430293?v=4?s=60" width="60px;" alt="Jim Graham"/><br /><sub><b>Jim Graham</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=jimgraham" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://t.me/littlepoint"><img src="https://avatars.githubusercontent.com/u/7611700?v=4?s=60" width="60px;" alt="Zhizhen He"/><br /><sub><b>Zhizhen He</b></sub></a><br /><a href="#tool-hezhizhen" title="Tools">🔧</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://amnesiak.org/me"><img src="https://avatars.githubusercontent.com/u/952059?v=4?s=60" width="60px;" alt="Tony Cheneau"/><br /><sub><b>Tony Cheneau</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=tcheneau" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/nicholas-l"><img src="https://avatars.githubusercontent.com/u/12977174?v=4?s=60" width="60px;" alt="Nicholas Latham"/><br /><sub><b>Nicholas Latham</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=nicholas-l" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://thara.dev"><img src="https://avatars.githubusercontent.com/u/1532891?v=4?s=60" width="60px;" alt="Tomochika Hara"/><br /><sub><b>Tomochika Hara</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=thara" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/dcarosone"><img src="https://avatars.githubusercontent.com/u/11495017?v=4?s=60" width="60px;" alt="Daniel Carosone"/><br /><sub><b>Daniel Carosone</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=dcarosone" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/MABruni"><img src="https://avatars.githubusercontent.com/u/100445384?v=4?s=60" width="60px;" alt="Miguel Angel Bruni Montero"/><br /><sub><b>Miguel Angel Bruni Montero</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=MABruni" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Walshkev"><img src="https://avatars.githubusercontent.com/u/77123083?v=4?s=60" width="60px;" alt="Kevin Walsh "/><br /><sub><b>Kevin Walsh </b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Walshkev" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://hereistheusername.github.io/"><img src="https://avatars.githubusercontent.com/u/33437051?v=4?s=60" width="60px;" alt="Xinglan Liu"/><br /><sub><b>Xinglan Liu</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=hereistheusername" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="http://www.hegghammer.com"><img src="https://avatars.githubusercontent.com/u/64712218?v=4?s=60" width="60px;" alt="Thomas Hegghammer"/><br /><sub><b>Thomas Hegghammer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Hegghammer" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/PiotrAleksander"><img src="https://avatars.githubusercontent.com/u/6314591?v=4?s=60" width="60px;" alt="Piotr Mrzygłosz"/><br /><sub><b>Piotr Mrzygłosz</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=PiotrAleksander" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://schaver.com/"><img src="https://avatars.githubusercontent.com/u/7584?v=4?s=60" width="60px;" alt="Mark Schaver"/><br /><sub><b>Mark Schaver</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=markschaver" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/n8layman"><img src="https://avatars.githubusercontent.com/u/25353944?v=4?s=60" width="60px;" alt="Nathan Layman"/><br /><sub><b>Nathan Layman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=n8layman" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/emmanuel-ferdman"><img src="https://avatars.githubusercontent.com/u/35470921?v=4?s=60" width="60px;" alt="Emmanuel Ferdman"/><br /><sub><b>Emmanuel Ferdman</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=emmanuel-ferdman" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Tenormis"><img src="https://avatars.githubusercontent.com/u/61572102?v=4?s=60" width="60px;" alt="Tenormis"/><br /><sub><b>Tenormis</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Tenormis" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://djon.es/blog"><img src="https://avatars.githubusercontent.com/u/225052?v=4?s=60" width="60px;" alt="David Jones"/><br /><sub><b>David Jones</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=djplaner" title="Documentation">📖</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/s-jacob-powell"><img src="https://avatars.githubusercontent.com/u/109111499?v=4?s=60" width="60px;" alt="S. Jacob Powell"/><br /><sub><b>S. Jacob Powell</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=s-jacob-powell" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/figdavi"><img src="https://avatars.githubusercontent.com/u/99026991?v=4?s=60" width="60px;" alt="Davi Figueiredo"/><br /><sub><b>Davi Figueiredo</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=figdavi" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/ChThH"><img src="https://avatars.githubusercontent.com/u/9499483?v=4?s=60" width="60px;" alt="CT Hall"/><br /><sub><b>CT Hall</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ChThH" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/meestahp"><img src="https://avatars.githubusercontent.com/u/177708514?v=4?s=60" width="60px;" alt="meestahp"/><br /><sub><b>meestahp</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=meestahp" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/qwloh"><img src="https://avatars.githubusercontent.com/u/14256866?v=4?s=60" width="60px;" alt="qwloh"/><br /><sub><b>qwloh</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=qwloh" title="Documentation">📖</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://firstsynth.dev"><img src="https://avatars.githubusercontent.com/u/118120847?v=4?s=60" width="60px;" alt="Ryan N"/><br /><sub><b>Ryan N</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=ryanncode" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="http://hals.app"><img src="https://avatars.githubusercontent.com/u/3185998?v=4?s=60" width="60px;" alt="Nils Henrik Hals"/><br /><sub><b>Nils Henrik Hals</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Strepto" title="Code">💻</a></td>
    </tr>
    <tr>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/alloutflo"><img src="https://avatars.githubusercontent.com/u/33363574?v=4?s=60" width="60px;" alt="Florian Meyer"/><br /><sub><b>Florian Meyer</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=alloutflo" title="Code">💻</a></td>
      <td align="center" valign="top" width="14.28%"><a href="https://github.com/Sherlock290"><img src="https://avatars.githubusercontent.com/u/73990305?v=4?s=60" width="60px;" alt="Sherlock290"/><br /><sub><b>Sherlock290</b></sub></a><br /><a href="https://github.com/foambubble/foam/commits?author=Sherlock290" title="Code">💻</a></td>
    </tr>
  </tbody>
</table>






Foam was inspired by [Zettelkasten methodology](https://zettelkasten.de/posts/overview).

Foam builds on [Visual Studio Code](https://code.visualstudio.com/), [GitHub](https://github.com/), and our [[recommended-extensions]].

## License

Foam is licensed under the [MIT license](LICENSE.txt).

[recommended-extensions]: user/getting-started/recommended-extensions.md 'Recommended Extensions'
[recipes]: user/recipes/recipes.md 'Recipes'
[frequently-asked-questions]: user/frequently-asked-questions.md 'Frequently Asked Questions'
[principles]: principles.md 'Principles'
[contribution-guide]: dev/contribution-guide.md 'Contribution Guide'

---

### User Index (`docs/user/index.md`)

# Using Foam

Foam is a personal knowledge management system built on [Visual Studio Code](https://code.visualstudio.com/) and [GitHub](https://github.com/). It helps you organize research, create discoverable notes, and publish your knowledge.

> See also [[frequently-asked-questions]].

## Key Features

- **Wikilinks** - Connect thoughts with `[[double bracket]]` syntax
- **Block anchors** - Link or embed specific paragraphs, list items, and headings with `[[note#^id]]`
- **Embeds** - Include content from other notes with `![[note]]` syntax
- **Backlinks** - Automatically discover connections between notes
- **Graph visualization** - See your knowledge network visually
- **Daily notes** - Capture timestamped thoughts
- **Templates** - Standardize note creation
- **Tags** - Organize and filter content

## Why Choose Foam?

- **Free and open source** - No subscriptions or vendor lock-in
- **Own your data** - Notes stored as standard Markdown files
- **VS Code integration** - Leverage powerful editing and extensions
- **Git-based** - Version control and collaboration built-in

Foam is like a bathtub: _What you get out of it depends on what you put into it._

## Getting Started

- [[installation]]
- [[get-started-with-vscode]]
- [[recommended-extensions]]
- [[first-workspace]]
- [[note-taking-in-foam]]
- [[sync-notes]]
- [[keyboard-shortcuts]]
- [[search-and-navigate-notes]]

Coming from Obsidian? See [[migrating-from-obsidian]].

## Features

- [[wikilinks]]
- [[footnotes]]
- [[block-anchors]]
- [[embeds]]
- [[foam-queries]]
- [[smart-folders]]
- [[tags]]
- [[backlinking]]
- [[daily-notes]]
- [[spell-checking]]
- [[graph-view]]
- [[note-properties]]
- [[templates]]
- [[paste-images-from-clipboard]]
- [[custom-markdown-preview-styles]]
- [[link-reference-definitions]]
- [[custom-snippets]]

## Recipes

[[recipes]] is a collection of user-contributed patterns that describe different ways you could utilize Foam or integrate it with other tools.

## Publishing

You can publish your Foam notes for consumption in different formats.
Examples: [[publish-to-github-pages]], [[generate-gatsby-site]], [[publish-to-vercel]]

See [[publishing]] for more details.

## Tools

- [[cli]] — work with your workspace from the terminal (`search`, `list`, `daily`, `lint`, and more)
- [[workspace-lint]]
- [[orphans]]
- [[foam-logging-in-vscode]]
- [[telemetry]]

[frequently-asked-questions]: frequently-asked-questions.md 'Frequently Asked Questions'
[installation]: getting-started/installation.md 'Installation'
[get-started-with-vscode]: getting-started/get-started-with-vscode.md 'Using Foam with VS Code Features'
[recommended-extensions]: getting-started/recommended-extensions.md 'Recommended Extensions'
[first-workspace]: getting-started/first-workspace.md 'Creating Your First Workspace'
[note-taking-in-foam]: getting-started/note-taking-in-foam.md 'Note-Taking in Foam'
[sync-notes]: getting-started/sync-notes.md 'Sync notes with source control'
[keyboard-shortcuts]: getting-started/keyboard-shortcuts.md 'Keyboard Shortcuts'
[search-and-navigate-notes]: recipes/search-and-navigate-notes.md 'Search and Navigate Notes'
[migrating-from-obsidian]: recipes/migrating-from-obsidian.md 'Coming from Obsidian'
[wikilinks]: features/wikilinks.md 'Wikilinks'
[footnotes]: features/footnotes.md 'Footnotes'
[block-anchors]: features/block-anchors.md 'Block Anchors'
[embeds]: features/embeds.md 'Note Embeds'
[foam-queries]: features/foam-queries.md 'Foam Queries'
[smart-folders]: features/smart-folders.md 'Smart Folders'
[tags]: features/tags.md 'Tags'
[backlinking]: features/backlinking.md 'Backlinks'
[daily-notes]: features/daily-notes.md 'Daily Notes'
[spell-checking]: features/spell-checking.md 'Spell Checking'
[graph-view]: features/graph-view.md 'Graph Visualization'
[note-properties]: features/note-properties.md 'Note Properties'
[templates]: features/templates.md 'Note Templates'
[paste-images-from-clipboard]: features/paste-images-from-clipboard.md 'Paste Images from Clipboard'
[custom-markdown-preview-styles]: features/custom-markdown-preview-styles.md 'Custom Markdown Preview Styles'
[link-reference-definitions]: features/link-reference-definitions.md 'Link Reference Definitions'
[custom-snippets]: features/custom-snippets.md 'Adding Custom Snippets'
[recipes]: recipes/recipes.md 'Recipes'
[publish-to-github-pages]: publishing/publish-to-github-pages.md 'GitHub Pages'
[generate-gatsby-site]: publishing/generate-gatsby-site.md 'Generate a site using Gatsby'
[publish-to-vercel]: publishing/publish-to-vercel.md 'Publish to Vercel'
[publishing]: publishing/publish-to-github-pages.md 'Publishing'
[cli]: tools/cli.md 'Command Line Interface'
[workspace-lint]: tools/workspace-lint.md 'Lint'
[orphans]: tools/orphans.md 'Orphaned Notes'
[foam-logging-in-vscode]: tools/foam-logging-in-vscode.md 'Foam logging in VsCode'
[telemetry]: tools/telemetry.md 'Telemetry'

---

### Inbox (`docs/inbox.md`)

# Inbox

Uncategorised thoughts, to be added

- Release notes
- Markdown Preview
  - It's possible to customise the markdown preview styling. **Maybe make it use local foam workspace styles for live preview of the site??**
    - See: <https://marketplace.visualstudio.com/items?itemName=bierner.markdown-preview-github-styles>
- Use VS Code [CodeTour](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) for onboarding
- Investigate other similar extensions:
  - [Unotes](https://marketplace.visualstudio.com/items?itemName=ryanmcalister.Unotes)
  - [vscode-memo](https://github.com/svsool/vscode-memo)
- Open in Foam
  - When you want to open a Foam published website in your own VS Code, we could have a "Open in Foam" link that opens the link in VS Code via a url binding (if possible), downloads the github repo locally, and opens it as a Foam workspace.
  - Every Foam could have a different theme even in the editor, so you'll see it like they see it
    - UI and layout design of your workspace can become a thing
- VS Code Notebooks API
  - <https://code.visualstudio.com/api/extension-guides/notebook>
- Future architecture
  - Could we do publish-related settings as a pre-push git hook, e.g. generating footnote labels
  - Running them on GitHub Actions to edit stuff as it comes in
    - Ideally, we shouldn't have to touch files, should be just markdown
- Looking at the errors/warnings/output panes makes me think, what kind of automated quality tools could we write.
  - Deduplication, finding similarities...
  - Thought Debugger?
  - Knowledge Debugger?
  - Janitor? Gardener?
  - Foam Compiler?
- Should support Netlify deploys out of the box
- Foam should tick at the same frequency as your brain, and the Foam graph you build should match the mental model you have in your head, making navigation effortless.
  - Maps have persistent topologies. As the graph grows, you should be able to visualise where an idea belongs. Maybe a literal map? And island? A DeckGL visualization?

Testing: This file is served from the /docs directory.

---

### Principles (`docs/principles.md`)

# Principles

## Table of Contents

- [Principles](#principles)
  - [Table of Contents](#table-of-contents)
  - [Foam enables you to do your best thinking](#foam-enables-you-to-do-your-best-thinking)
  - [Foam wants you to own your thoughts](#foam-wants-you-to-own-your-thoughts)
  - [Foam helps you share your thoughts with the world.](#foam-helps-you-share-your-thoughts-with-the-world)
  - [Foam allows people to collaborate in discovering better ways to work, together.](#foam-allows-people-to-collaborate-in-discovering-better-ways-to-work-together)
  - [Foam is for hackers, not only for programmers](#foam-is-for-hackers-not-only-for-programmers)

## Foam enables you to do your best thinking

- **Foam works for you, you don't work for Foam.** You should be able to focus on your work and not fight against Foam, or having to perform fiddly operations or maintenance jobs to keep Foam happy.
- **Foam is not a package deal.** You must be able to adopt only the parts of Foam that you want. There must be no tight coupling between Foam's features.
- **Foam is a starting point** You must be able to customise how foam looks and feels, and combine it with other tools you find helpful in your personal workflow.
- **Foam is not a philosophy.** Whether you use a methodology like Zettelkasten is up to you. **You should be able to use Foam without joining a cult.**

## Foam wants you to own your thoughts

- **Foam doesn't want your data.** You can store your documents wherever you want. Some of Foam's suggested workflows include GitHub, if you don't want to use it to store your data, or you want to stop using it in the future, you should be able to migrate to alternative storage options. If you choose to not upload your notes to any cloud service or remote repository, remember to keep frequent local and occasional offsite backups of your data!
- **Foam should not lock you in.** Foam's content files, structure and metadata should be in interoperable format that supports migrating it to another tool if you prefer to. Users of Foam should be able to develop and share such tools freely.
- **Foam should not leak your secrets.** Nobody, including the developers of Foam, should have access to your personal knowledge graph unless you choose to give it to them. Foams should always be private by default, but [easy to share](#foam-helps-you-share-your-thoughts-with-the-world) if you choose to.

## Foam helps you share your thoughts with the world.

This principle may seem like it contradicts [Foam wants you to own your thoughts](#foam-wants-you-to-own-your-thoughts), but it's actually a compatible corollary. You should be able to do both, because:

> [...] environments that build walls around good ideas tend to be less innovative in the long run than more open-ended environments. Good ideas may not want to be free, but they do want to connect, fuse, recombine. —_Steven Johnson, Where Good Ideas Come From_

- **Foam should make it easy to publish your knowledge graph.** With zero code, you should be able to make your graph public to the world. You should have full control over how it looks, feels, and where it's hosted.
- **Foam should make it easy to collaborate on ideas.** Foam should allow you to work closely together with your collaborators, and accept feedback, input and improvements from others.
- **Foam should make it easy to publish what you choose.** Foam should double as a low-barrier blog/publishing platform, so you can share content to an audience without inviting them to intrude on your entire workspace.

## Foam allows people to collaborate in discovering better ways to work, together.

- **Foam is a collection of ideas.** Foam was released to the public not to share the few good ideas in it, but to learn many good ideas from others. As you improve your own workflow, share your work on your own Foam blog.
- **Foam is open for contributions.** If you use a tool or workflow that you like that fits these principles, please contribute them back to the Foam template as [[recipes]], [[recommended-extensions]] or documentation in [this workspace](https://github.com/foambubble/foam). See also: [[contribution-guide]].
- **Foam is open source.** Feel free to fork it, improve it and remix it under the terms of our [MIT license](LICENSE.txt).
- **No idea is too big.** If it doesn't fit with Foam's core workflow, we might make it a [[recipes]] page instead.

## Foam is for hackers, not only for programmers

While Foam uses tools popular among computer programmers, Foam should be inclusive of everyone who wants to improve their own workflow to improve themselves.

- **Foam embraces the hacker mindset.** The target audience for Foam are people who look for creative ways to improve their ability to collect and organise information.
- **Foam is not just for programmers.** If you're a programmer, feel free to write scripts and extensions to support your own workflow, and publish them for others to use, but the out of the box Foam experience should not require you to know how to do so. You should, however, be curious and open to adopting new tools that are unfamiliar to you, and evaluate whether they could work for you.
- **Foam is for everyone** As a foam user, you support everyone's quest for knowledge and self-improvement, not only your own, or folks' who look like you. All participants in Foam repositories, discussion forums, physical and virtual meeting spaces etc are expected to respect each other as described in our [[code-of-conduct]]. **Foam is not for toxic tech bros.**

[recipes]: user/recipes/recipes.md "Recipes"
[recommended-extensions]: user/getting-started/recommended-extensions.md "Recommended Extensions"
[contribution-guide]: dev/contribution-guide.md "Contribution Guide"
[code-of-conduct]: dev/code-of-conduct.md "Code of Conduct"

---

### Dev Code Of Conduct (`docs/dev/code-of-conduct.md`)

---
redirect_from:
  - /code-of-conduct
---

# Code of Conduct

We follow the [Contributor Covenant](https://www.contributor-covenant.org/) code of conduct.

## Our Pledge

We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.

## Our Standards

Examples of behavior that contributes to a positive environment for our
community include:

- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologizing to those affected by our mistakes,
  and learning from the experience
- Focusing on what is best not just for us as individuals, but for the
  overall community

Examples of unacceptable behavior include:

- The use of sexualized language or imagery, and sexual attention or
  advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email
  address, without their explicit permission
- Other conduct which could reasonably be considered inappropriate in a
  professional setting

## Enforcement Responsibilities

Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.

Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.

## Scope

This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at `riki.code+foam@gmail.com`.

All complaints will be reviewed and investigated promptly and fairly.

All community leaders are obligated to respect the privacy and security of the
reporter of any incident.

## Enforcement Guidelines

Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:

### 1. Correction

**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.

**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.

### 2. Warning

**Community Impact**: A violation through a single incident or series
of actions.

**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.

### 3. Temporary Ban

**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.

**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.

### 4. Permanent Ban

**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.

**Consequence**: A permanent ban from any sort of public interaction within
the community.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
<https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.

Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).

[homepage]: https://www.contributor-covenant.org

For answers to common questions about this code of conduct, see the FAQ at
<https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.

---

### Dev Contribution Guide (`docs/dev/contribution-guide.md`)

# Contribution Guide

The contribution guide has moved to [CONTRIBUTING.md](../../CONTRIBUTING.md) at the repository root.

---

### Dev Devcontainers (`docs/dev/devcontainers.md`)

# Using Dev Containers

Foam provides a [devcontainer](https://devcontainer.ai/) configuration to make it easy to contribute without installing Node and Yarn locally.

## Quick start

1. Install [VS Code](https://code.visualstudio.com/) and the [Dev Containers](https://aka.ms/vscode-remote/download/extension) extension.
2. Open the Foam repository in VS Code.
3. Run **Dev Containers: Reopen in Container** from the command palette.

This will build a Docker image with Node 18 and install dependencies using `yarn install`. Once ready you can run the usual build and test commands from the integrated terminal.

---

### Dev Releasing Foam (`docs/dev/releasing-foam.md`)

# Releasing Foam

Foam uses [Changesets](https://github.com/changesets/changesets) to manage versions and changelogs across the monorepo (`foam-vscode`, `@foam/cli`, `@foam/core`). Changesets owns the arithmetic — which package gets which bump, and assembling `CHANGELOG.md`. Deciding _what_ to write is covered by the [changelog rules](#changelog-rules) below.

## Writing changesets

Fragments are written at release time, reconstructed from the history on `main` since the last release: see [Generating fragments from git history](#generating-fragments-from-git-history). Changes don't carry them, so a pull request leaves `.changeset/` alone.

### ⚠️ Changes to `@foam/core` must also bump its dependents

`foam-vscode` and `@foam/cli` both **bundle** `@foam/core` at build time (esbuild inlines it), and both declare it as a `devDependency` — not a runtime `dependency`. Because of that, Changesets' automatic internal-dependency bumping (`updateInternalDependencies`) does **not** cascade a `@foam/core` bump to them. It won't add the fragments for you.

So whenever a change touches `packages/foam-core`, the changeset must **also** include `foam-vscode` and `@foam/cli` (each usually `patch`), so their republished bundles ship with a correct version and a changelog entry. If you only bump `@foam/core`, the extension and CLI will silently publish updated code under a stale version number.

Rule of thumb: **if `@foam/core` is in the fragment, `foam-vscode` and `@foam/cli` almost always belong there too** — unless the core change is genuinely internal-only and reaches neither the extension nor the CLI.

## Changelog rules

### Does the change need a fragment?

Yes, if it changes behavior that users of a published package can observe: `foam-vscode`, `@foam/cli`, `@foam/core`. (`@foam/graph-view`, `@foam/mcp` and `@foam/agent-loop` are listed under `ignore` in `.changeset/config.json` and never get fragments.)

No, for:

- documentation, `CLAUDE.md`, `.agent/` specs
- test-only commits — the change they cover carries the fragment
- refactors with no user-visible effect and no public API change
- build and tooling changes that don't alter what ships

### Which bump?

Foam is pre-1.0, so these are conventions rather than strict semver:

| Bump    | `@foam/core`                                                                   | `foam-vscode` / `@foam/cli`                             |
| ------- | ------------------------------------------------------------------------------ | ------------------------------------------------------- |
| `major` | reserved — decide deliberately                                                 | reserved — decide deliberately                          |
| `minor` | new or changed public API surface (new export, new subpath, changed signature) | new user-facing feature                                 |
| `patch` | bug fix, security fix, internal change that still ships                        | bug fix, security fix, manifest or user-facing copy fix |

When several commits fold into one fragment, use the highest bump any of them warrants.

### Writing the entry

The entry is read by users, not by developers. Make it as short as it can be while still telling them what changed: usually one line, rarely more than two sentences.

- Say what changed, not why it was broken or how it was fixed. Causes, mechanisms and internal names belong in the commit message.
- If behavior narrowed, say so, and say what to do instead.
- Name a changed API only in a `@foam/core` entry, and only name it.
- Several related fixes can share one entry as a list, one line per item.
- Reference the issue number when there is one, as `(#1215)`.
- Don't reuse the commit subject verbatim — commit subjects are written for developers.

For example:

```markdown
Notes in folders listed in `files.watcherExclude` are no longer left out of the workspace. To exclude a folder, use `foam.files.exclude`.
```

not a paragraph on what `files.watcherExclude` is for, why honouring it saved no CPU, and how the CLI differed.

## Generating fragments from git history

At release time, for anything that shipped without a fragment:

1. List what landed since the last release (tags are `vscode@<version>`, `cli@<version>`, `core@<version>`):

   ```
   git log vscode@<last-version>..HEAD --oneline
   ```

2. Group the commits into coherent user-facing changes. Several commits (a fix, its tests, a docs touch-up) usually become one fragment; occasionally one commit becomes two.
3. For each group apply the rules above: does it need a fragment, which packages, which bump, and what does the user need to know.
4. Apply the core cascade rule to every fragment that names `@foam/core`.
5. Write each one as `.changeset/<kebab-case-name>.md`:

   ```markdown
   ---
   'foam-vscode': patch
   ---

   The entry text.
   ```

The `/update-changelog` slash command can draft these for commits already on `main`.

Fragments don't need to be committed before `yarn version-packages` runs — it reads them off disk. Committing them first is still worthwhile if you want the intent recorded independently of the generated changelog.

Nothing in CI enforces any of this; it's a review-time and release-time responsibility.

## Cutting a release

1. Get to the latest code
   - `git checkout main && git fetch && git rebase`
2. Sanity checks
   - `yarn reset`
   - `yarn test`
3. Make sure every shipped change since the last release has a fragment in `.changeset/`
   - If not, write the missing ones — see [Generating fragments from git history](#generating-fragments-from-git-history)
   - **If any change touched `@foam/core`, confirm `foam-vscode` and `@foam/cli` are also covered by a fragment** (see the warning above). Their bundles pick up core changes at build time, but Changesets will not bump their versions automatically.
4. Apply the fragments — bumps versions in each affected `package.json`, regenerates `CHANGELOG.md`, and deletes the consumed fragments
   - `yarn version-packages`
5. Review and commit the result
   - Inspect the generated `CHANGELOG.md` and version bumps
   - Update `./packages/foam-vscode/WHATS_NEW.md` if the release has something users should act on or learn to use. It is shown on update when its _content hash_ changes, so leaving it untouched shows nothing — appropriate for a release with no new features.
   - `git add -A && git commit -m "Release"`
   - `yarn tag-release` - Create per-package tags (`vscode@<version>`, `cli@<version>`, `core@<version>`):
     - The script reads each package's current version from `package.json` and skips any tag that already exists.
6. Publish
   - `yarn release` to release them all, otherwise
     - `yarn release-extension` (packages and publishes to VS Marketplace and OpenVSX)
     - `yarn release-cli` (packages and publishes `@foam/cli` to npm as `foam-cli`)
     - `yarn release-core` (publishes `@foam/core` to npm)
7. Push
   - `git push && git push --tags`
8. Update the release notes in GitHub
   - In GitHub, top right, click on "releases"
   - Select "tags" in top left
   - Select the tag that was just released, click "edit" and copy release information from `CHANGELOG.md`
   - Publish (no need to attach artifacts)
9. Announce on Discord

Steps 1 to 8 should really be replaced by a GitHub action...

---

### Dev Testing Conventions (`docs/dev/testing-conventions.md`)

# Testing in Foam VS Code Extension

This document explains the testing strategy and conventions used in the Foam VS Code extension.

## Test File Types

We use two distinct types of test files, each serving different purposes:

### `.test.ts` Files - Pure Unit Tests

- **Purpose**: Test business logic and algorithms in complete isolation
- **Dependencies**: No VS Code APIs dependencies
- **Environment**: Vitest with Node.js
- **Speed**: Very fast execution
- **Location**: Throughout the codebase alongside source files

### `.spec.ts` Files - Integration Tests with VS Code APIs

- **Purpose**: Test features that integrate with VS Code APIs and user workflows
- **Dependencies**: Will likely depend on VS Code APIs (`vscode` module), otherwise avoid incurring the performance hit
- **Environment**: Can run in TWO environments:
  - **Mock Environment**: Vitest with VS Code API mocks (fast)
  - **Real VS Code**: Full VS Code extension host (slow but comprehensive)
- **Speed**: Depends on environment (see performance section below)
- **Location**: Primarily in `src/vscode/features/` and service layers

## Key Principle: Environment Flexibility for `.spec.ts` Files

**`.spec.ts` files use VS Code APIs**, but they can run in different environments:

- **Mock Environment**: Uses our VS Code API mocks for speed
- **Real VS Code**: Uses actual VS Code extension host for full integration testing

This dual-environment capability allows us to:

- Run specs quickly during development (mock environment)
- Verify full integration during CI/CD (real VS Code environment)
- Gradually migrate specs to mock-compatible implementations

## Performance Comparison

| Test Type             | Environment            | Typical Duration | VS Code APIs     |
| --------------------- | ---------------------- | ---------------- | ---------------- |
| **`.test.ts`**        | Vitest (Node.js)       | fastest          | **No**           |
| **`.spec.ts` (mock)** | Vitest + VS Code Mocks | fast             | **Yes** (mocked) |
| **`.spec.ts` (real)** | VS Code Extension Host | sloooooow.       | **Yes** (real)   |

## Running Tests

### Available Commands

- **`yarn test:unit`**: Runs `.test.ts` files (no VS Code dependencies) + `@unit-ready` marked `.spec.ts` files using mocks
- **`yarn test:unit-without-specs`**: Runs only `.test.ts` files
- **`yarn test:e2e`**: Runs all `.spec.ts` files in full VS Code extension host
- **`yarn test`**: Runs both unit and e2e test suites sequentially

## Mock Environment Migration

We're gradually enabling `.spec.ts` files to run in our fast mock environment while maintaining their ability to run in real VS Code.

### The `@unit-ready` Annotation

Spec files marked with `/* @unit-ready */` can run in both environments:

```typescript
/* @unit-ready */
import * as vscode from 'vscode';
// ... test uses VS Code APIs but works with our mocks
```

### Common Migration Fixes

**Configuration defaults**: Our mocks don't load package.json defaults

```typescript
// Before
const format = getFoamVsCodeConfig('openDailyNote.filenameFormat');

// After (defensive)
const format = getFoamVsCodeConfig(
  'openDailyNote.filenameFormat',
  'yyyy-mm-dd'
);
```

**File system operations**: Ensure proper async handling

```typescript
// Mock file operations are immediate but still async
await vscode.workspace.fs.writeFile(uri, content);
```

### When NOT to Migrate

Some specs should remain real-VS-Code-only:

- Tests verifying complex VS Code UI interactions
- Tests requiring real file system watching with timing
- Tests validating extension packaging or activation
- Tests that depend on VS Code's complex internal state management

## Mock System Capabilities

Our `vscode-mock.ts` provides comprehensive VS Code API mocking:

## Contributing Guidelines

When adding new tests:

1. **Choose the right type**:

   - Use `.test.ts` for pure business logic with no VS Code dependencies
   - Use `.spec.ts` for anything that needs VS Code APIs

2. **Consider mock compatibility**:

   - When writing `.spec.ts` files, consider if they could run in mock environment
   - Add `/* @unit-ready */` if the test works with our mocks

3. **Follow naming conventions**:

   - Test files should be co-located with source files when possible
   - Use descriptive test names that explain the expected behavior

4. **Performance awareness**:
   - Prefer unit tests for business logic (fastest)
   - Use mock-compatible specs for VS Code integration (fast)
   - Reserve real VS Code specs for complex integration scenarios (comprehensive)

This testing strategy gives us the best of both worlds: fast feedback during development and comprehensive integration verification when needed.

## Graph Webview (`@foam/graph-view`)

The webview component has its own test stack, separate from the extension tests.

- **Framework**: [Vitest](https://vitest.dev/) with [happy-dom](https://github.com/capricorn86/happy-dom) for a browser-like environment
- **Location**: Test files live in `packages/foam-graph/src/`
- **Command**: `yarn workspace @foam/graph-view test`

The webview tests focus on the framework-agnostic library code in `src/lib/` (graph utilities, color logic, painter). Lit component rendering tests can be added as the component grows.

---

### User Frequently Asked Questions (`docs/user/frequently-asked-questions.md`)

# Frequently Asked Questions

- [Frequently Asked Questions](#frequently-asked-questions)
  - [Links/Graphs/BackLinks don't work. How do I enable them?](#linksgraphsbacklinks-dont-work-how-do-i-enable-them)
  - [I don't want Foam enabled for all my workspaces](#i-dont-want-foam-enabled-for-all-my-workspaces)
  - [I want to publish the graph view to GitHub pages or Vercel](#i-want-to-publish-the-graph-view-to-github-pages-or-vercel)
  - [Does Foam collect any data?](#does-foam-collect-any-data)

## Links/Graphs/BackLinks don't work. How do I enable them?

- Ensure that you have all the [[recommended-extensions]] installed in Visual Studio Code
- Reload Visual Studio Code by running `Cmd` + `Shift` + `P` (`Ctrl` + `Shift` + `P` for Windows), type "reload" and run the **Developer: Reload Window** command to for the updated extensions take effect
- Check the formatting rules for links on [[wikilinks]]

## I don't want Foam enabled for all my workspaces

Any extension you install in Visual Studio Code is enabled by default. Given the philosophy of Foam, it works out of the box without doing any configuration upfront. In case you want to disable Foam for a specific workspace, or disable Foam by default and enable it for specific workspaces, it is advised to follow the best practices as [documented by Visual Studio Code](https://code.visualstudio.com/docs/editor/extension-marketplace#_manage-extensions)

## I want to publish the graph view to GitHub pages or Vercel

If you want a different front-end look to your published foam and a way to see your graph view, we'd recommend checking out these templates:

- [foam-gatsby](https://github.com/mathieudutour/foam-gatsby-template) by [Mathieu Dutour](https://github.com/mathieudutour)
- [foam-gatsby-kb](https://github.com/hikerpig/foam-template-gatsby-kb) by [hikerpig](https://github.com/hikerpig)

## Does Foam collect any data?

Foam collects anonymous usage data (which commands are used, which features are configured) to help prioritize development. No note content, file names, or personal information is ever collected.

Foam follows VS Code's global telemetry setting (`telemetry.telemetryLevel`). If you have disabled telemetry in VS Code, Foam will not send any data.

To inspect what is being sent, set the Foam log level to `Debug` (run `Foam: Set log level` from the command palette) — telemetry events will appear in the Foam output channel. See [[foam-logging-in-vscode]] for details.

See [[telemetry]] for the full list of collected data and opt-out instructions.

[recommended-extensions]: getting-started/recommended-extensions.md 'Recommended Extensions'
[wikilinks]: features/wikilinks.md 'Wikilinks'
[telemetry]: tools/telemetry.md 'Telemetry'
[foam-logging-in-vscode]: tools/foam-logging-in-vscode.md 'Foam logging in VsCode'

---

### Dev Design Core Model And Api Review (`docs/dev/design/core-model-and-api-review.md`)

# Core Model & API Review — Improvement Spec

- **Date:** 2026-08-09
- **Scope:** `@foam/core` information model and services, package/API architecture, and the seams to `foam-vscode`, `@foam/cli`, and `@foam/mcp`. Performance items are included where they fall out of the model review.
- **Method:** full read of `packages/foam-core/src/model/*` and `src/services/*`, the export subsystem, the consumer packages' integration points, the perf instrumentation (`load-profiler`, benches, `scripts/perf/gate.mjs`), and the open issue tracker. Every finding cites `file:line` against commit `8b03256`.
- **Legend:** each proposal carries **Effort** (S ≈ hours, M ≈ 1–3 days, L ≈ 1–2 weeks+), **Breaking** (against the `@foam/core` public surface in `packages/foam-core/src/index.ts`, or user-visible behavior), and **Impact** with rationale.

---

## Executive summary

The core model is in good shape structurally — the reversed-trie workspace index, the incremental graph, the `PublishTarget` export abstraction, and the perf-gate CI are all well-designed. The review found no architectural rot, but it did find:

1. **A handful of genuine correctness bugs**, including one silent data-loss case in the workspace index (case-colliding filenames), a divergence between the incremental graph and a full rebuild, and rename/edit paths that can corrupt files (no overlap detection, duplicated definition edits).
2. **A semantic gap advertised but not implemented:** aliases are offered by link completion but never participate in link resolution, so the extension can suggest a link it will then render as broken.
3. **Lifecycle leaks** (tags never disposed, providers never disposed, one failing feature aborts the whole extension activation and strands live resources).
4. **Avoidable hot-path costs** that map directly onto the two open perf issues (#1375, #1689): a wasted nested tree-walk in the block parser, an O(n·m) file matcher, a full SHA-1 + deserialize on every parser-cache *hit*, and a full-workspace clone per rename.
5. **API-surface debt:** a 297-symbol barrel of which ~34% has no in-repo consumer, host concerns embedded in the platform-agnostic core (telemetry endpoint, VS Code-only config getters), and duplicated serializers that make the CLI and MCP emit different wire formats for the same data.
6. **Doc drift:** `CLAUDE.md` describes the pre-`foam-core` repo layout and actively misdirects contributors (and agents).

The roadmap at the end sequences these into four phases. Phase 1 (correctness + leaks) is entirely non-breaking and roughly two weeks of work; the breaking items are concentrated in Phase 4 and can ride a single minor/major release.

---

## 1. Correctness fixes

### 1.1 Case-colliding filenames silently overwrite each other in the workspace index

`FoamWorkspace` keys its trie by a reversed, **lowercased** path (`workspace.ts:350-365`, `normalize` at `:528`). `/a/Note.md` and `/a/note.md` produce the identical key, so the second file **replaces** the first in `_resources`, and `set()` emits `onDidUpdate` instead of `onDidAdd` (`workspace.ts:127-137`) — which then desynchronizes the graph (it disconnects the old path while connecting the new one, leaving stale backlinks). The existing #1303 regression test (`workspace.test.ts:187-209`) uses files in *different* directories, so this collision is untested. The model currently has two incompatible notions of identity: `find(URI)` is case-insensitive while `URI.isEqual` (`uri.ts:236-244`) is case-sensitive.

**Proposal:** store exact-case keys in the trie with a case-insensitive lookup layer (bucket resources under the lowercased key), define identity policy in one place, and add the missing same-directory regression test.

**Effort:** M · **Breaking:** No (fixes a currently-broken case) · **Impact:** High — silent data loss in the model; affects any vault with case-variant filenames (common on case-sensitive filesystems / git checkouts).

### 1.2 Incremental graph diverges from a rebuild when an added file changes a non-placeholder resolution

`onResourceAdded` (`graph.ts:140-144`) only re-resolves sources currently pointing at a *placeholder*. But adding a file can also change resolution of a link that already resolves to a real note, because ambiguity is broken by path sort (`workspace.ts:290`) and directory-index suffix match (`workspace.ts:229-239`). Example: `[[attachment-a.pdf]]` resolves to `/path/to/more/attachment-a.pdf`; adding `/path/to/attachment-a.pdf` should re-point it — the full-rebuild path asserts exactly this (`graph.test.ts:183-221`), the incremental path misses it. The comment at `graph.ts:136-138` acknowledges the missing inverse-resolution capability. `graph-incremental.test.ts` has no "add steals an already-resolved target" case, and the `[flat]` perf gate (`workspace-graph.bench.ts:132-142`) only covers the update path.

**Proposal:** on add, additionally reconnect sources whose links resolve *by identifier* to the new resource's basename (the workspace can expose "which identifiers does this URI answer to"); add the missing incremental test and extend the scaling bench to add/delete paths.

**Effort:** M · **Breaking:** No · **Impact:** High — the graph (backlinks panel, orphans, graph view) is quietly wrong after a common operation until the next full reload.

### 1.3 Rename/edit pipeline can corrupt files

Three compounding defects:

- `TextEdit.apply` (`text-edit.ts:18-50`) has **no overlap detection** — overlapping ranges silently corrupt the document.
- The parser resolves every reference link to the **same `NoteLinkDefinition` object** (`markdown-parser.ts:204-206`), so a file with `[a][ref]` and `[b][ref]` makes `heading-edit` emit **two edits with the identical range** (`heading-edit.ts:85-118`, `:215-247`) — no dedup anywhere, including `commands/rename.ts:47-67`. Combined with the missing overlap check, the definition line is rewritten twice.
- `createUpdateLinkEdit` throws on external links (`markdown-link.ts:100-102`) and `heading-edit.ts:126` calls it outside its try/catch, so one odd link aborts an entire rename.

**Proposal:** dedupe edits by range before applying; make `TextEdit.apply` throw on overlaps; guard the `analyzeLink`/`createUpdateLinkEdit` call sites consistently. Add the `[a][ref] + [b][ref]` test.

**Effort:** S · **Breaking:** No · **Impact:** High — these are the operations users trust most (rename heading/block across the vault); failure mode is silent file corruption.

### 1.4 CLI/MCP rename leaves markdown-style links dangling

`link-integrity.ts:71` only rewrites `wikilink` connections; markdown `[text](note.md)` links are documented as "delegated to VS Code built-in" (`link-integrity.test.ts:134`). That fallback exists only in the editor — `commands/rename.ts:112` and `commands/note.ts:306` are the CLI/MCP path, where markdown links silently break on rename.

**Proposal:** handle `link.type === 'link'` in `link-integrity`, optionally behind a `linkTypes` option so the VS Code host can keep delegating.

**Effort:** M · **Breaking:** Behavior change for CLI/MCP renames (strictly a fix) · **Impact:** High for CLI/MCP users — renames are currently unsafe outside the editor.

### 1.5 Tag range extraction has wrong-position bugs

- Frontmatter tag ranges use substring search (`markdown-parser.ts:384-386`): tag `foo` matches inside `foobar` on an earlier line, producing a wrong range — and `TagEdit` writes edits at exactly those ranges.
- Hashtag ranges assume a single-line text node (`markdown-parser.ts:399-408`): a `#tag` on the second line of a multi-line paragraph gets a range on the wrong line/column. All existing tests use single-line paragraphs.
- `tag-edit.ts:79-85` distinguishes hashtag vs frontmatter tags by comparing the **range length**, coupled invisibly to how the parser computes ranges two files away.

**Proposal:** fix both range computations (word-boundary anchoring; newline-aware offset mapping) with targeted tests, and add a `source: 'inline' | 'frontmatter'` discriminator to `Tag` (`note.ts:75-78`) so `tag-edit` drops the heuristic (requires a `CACHE_VERSION` bump in `foam-vscode/src/vscode/services/cache.ts:37`).

**Effort:** M · **Breaking:** `Tag` field addition is additive; cached-resource schema bump only · **Impact:** Medium-High — tag rename writes edits at wrong positions in these cases; also unblocks #1240-adjacent tag work.

### 1.6 Assorted small correctness fixes (batch)

| Fix | Where |
|---|---|
| `useAngles` off-by-one: target *starting* with a space isn't angle-wrapped | `markdown-link.ts:124`, `note.ts:55` (`indexOf(' ') > 0` → `includes(' ')`) |
| Missing null check: `workspace.find(source)` result dereferenced | `markdown-provider.ts:205` |
| `.sort()` without comparator on objects — sorts nothing | `markdown-provider.ts:280` |
| `/m` vs `/gm` inconsistency stripping block-anchor markers | `markdown-provider.ts:55` vs `:68` |
| `String.replace` with string containing user text interprets `$` patterns | `tag-edit.ts:238` |
| Attachment extension case inconsistency: `photo.PNG` accepted but misclassified | `attachment-provider.ts:39,65-67,71` |
| Watcher change handler race: two rapid changes to one file, last *read* wins not last *event* | `foam.ts:69-73` — serialize per-URI |
| Frontmatter `tags` line lookup can be `undefined` → tags silently vanish | `markdown-parser.ts:376-378` |

**Effort:** S (one batch PR) · **Breaking:** No · **Impact:** Medium — each is small, but all are user-visible in edge cases and cheap to fix together.

---

## 2. Lifecycle & resource management

### 2.1 `foam.dispose()` leaks `FoamTags`; workspace never disposes providers

`bootstrap`'s disposer (`foam.ts:110-114`) disposes subscriptions, workspace, and graph — never `tags`, whose three workspace listeners (`tags.ts:41-45`) and emitter leak. `FoamTags.dispose()` itself also skips its emitter (unlike `FoamGraph.dispose()`, `graph.ts:263-265`). Separately, `FoamWorkspace.dispose` (`workspace.ts:460-464`) never disposes registered providers even though `ResourceProvider extends IDisposable` (`provider.ts:6`).

**Proposal:** fix both; better, give `Foam` a `DisposableStore` so new members can't be forgotten.

**Effort:** S · **Breaking:** No · **Impact:** Medium — leaks on every reload/deactivate cycle; matters for long-lived hosts and the embeddable MCP library.

### 2.2 One failing feature aborts extension activation and strands live resources

`extension.ts:174` joins all features with `Promise.all`; a single rejection means `context.subscriptions.push(foam, watcher, parserCache, …)` at `:185` never runs — `Foam`, the watcher, and the parser cache stay alive and undisposed, and `extendMarkdownIt` is silently lost (preview loses all Foam rendering). Features are anonymous functions (`features/index.ts:15-28`), so the error can't even name the culprit.

**Proposal:** switch to `Promise.allSettled` with per-feature error logging; push core resources into `context.subscriptions` immediately after bootstrap; give features an `id` (and optional `supports: 'node' | 'web'`) — `interface FoamFeature { id; supports?; activate(ctx, foam) }`. The `id` also fixes the acknowledged telemetry-key collision risk (`types.d.ts:11-12`) and gives the web build a declarative way to skip Node-only features (see §6.2).

**Effort:** M · **Breaking:** No (internal to the extension) · **Impact:** High — converts "any feature bug bricks Foam" into "one feature degrades".

### 2.3 Leaked registrations in graph-webview

`graph-webview/index.ts:21` (`onDidChangeConfiguration`) and `:62` (`registerCommand('foam-vscode.show-graph', …)`) discard their disposables; every other feature pushes them into `context.subscriptions`.

**Effort:** S · **Breaking:** No · **Impact:** Low — orphaned registrations on deactivate/reactivate.

### 2.4 Honor `FoamTags`' `debounceFor` parameter

`tags.ts:33` accepts `debounceFor` but `:40` hardcodes `debounce(..., 500)` — the value is used only as an on/off flag, and `bootstrap` never passes it, so tags are undebounced in production.

**Effort:** S · **Breaking:** No · **Impact:** Low alone; pairs with §3.4.

---

## 3. Performance

These target the two open perf axes tracked by the bench suite (`workspace-graph.bench.ts:14-30`, #1375) and the slow-load report (#1689, `load-profiler.ts:13-14`). The perf-gate CI (`scripts/perf/gate.mjs`: fail at 2.0×, warn at 1.3×; `[linear]`≤1.8, `[flat]`≤1.0 normalized) will verify each claim.

### 3.1 Block parser does a wasted nested tree-walk per node

`blocksPlugin.visit` (`markdown-parser.ts:509-518`) calls `getDirectText(node)` — itself a **full subtree visit** (`:332-340`) — for every paragraph/listItem/blockquote/heading, then discards the text whenever there's no `^` block anchor, which is nearly always. This is a constant-factor ~2× traversal on flat documents and O(n·depth) on nested ones — the single largest avoidable cost in the parse path, which the profiler already identifies as the load bottleneck (`load-profiler.ts:218-219`, parse is super-linear in note size). Also: `note.blocks.some(...)` in the same loop is O(blocks²) (`:537`), and each own-line blockquote anchor re-splits the whole source (`:570`).

**Proposal:** gate `getDirectText` on a cheap "does this node's source range contain `^`" check; replace the `some` with a `Set`; split the source into lines once per parse and share with the footnote scan (`:237`).

**Effort:** S · **Breaking:** No · **Impact:** High — directly attacks #1689/#1375; expected double-digit-% parse-time reduction on typical vaults, verifiable in `markdown-parser.bench.ts`.

### 3.2 Parser cache hits still pay SHA-1 + full deserialize

`cachedParser` (`markdown-parser.ts:275-301`) hashes the entire document (SHA-1, `utils/core.ts:49`) on every call, and a hit still runs `Resource.fromJSON` (`foam-vscode/src/vscode/services/cache.ts:201-210`). During typing this is the hot path, and the profiler reports it as a cheap "hit".

**Proposal:** let the host pass a cheaper validity token (document version/mtime) so unchanged documents skip hashing entirely; collapse `cache.has` + `cache.get` into one call; consider memoizing the last deserialized resource per URI.

**Effort:** M · **Breaking:** No (additive cache API) · **Impact:** Medium-High — removes per-keystroke work proportional to note size.

### 3.3 O(n·m) file matcher on the VS Code hot path

`FileListBasedMatcher.match()` filters with `Array.includes` over a `string[]` (`datastore.ts:168-170`); `isMatch` is O(n) per call. This is the matcher VS Code selects in the common case (`editor.ts:495-502`) — on a 10k-file vault a single `match(allFiles)` is ~10⁸ comparisons. The class carries its own "to be refactored later" note (`:150`).

**Proposal:** back it with a `Set<string>`. While in there: its `include`/`exclude` fields are decorative (never consulted) — either wire or remove them. This is also the natural place to add **`.gitignore` support (#1388)**, the most-requested open datastore issue.

**Effort:** S (Set) + M (gitignore) · **Breaking:** No · **Impact:** Medium-High — removes a quadratic on load and on every matcher refresh; #1388 has standing user demand.

### 3.4 `FoamTags` rebuilds the entire tag index on every file event

`tags.update()` (`tags.ts:51-61`) is a full O(total tags) rebuild wired to all three workspace events (`:42-46`), unlike the graph which is incremental. Every panel listening to `tags.onDidUpdate` then refreshes wholesale.

**Proposal:** incremental update using the `{old, new}` payload the workspace already provides (index tag locations by resource as well as label).

**Effort:** M · **Breaking:** No · **Impact:** Medium — flattens per-edit cost in tag-heavy vaults; pairs with §2.4 and §4.6.

### 3.5 `link-integrity` clones the whole workspace per rename

`buildFutureWorkspace` (`link-integrity.ts:13-26`) copies every resource into a fresh `FoamWorkspace` to answer one identifier question — a full second index per rename on large vaults.

**Proposal:** an overlay resolver over the live workspace (consult the overlay first, fall through).

**Effort:** M · **Breaking:** No · **Impact:** Medium — rename latency on large vaults.

### 3.6 Other measured/mechanical wins (batch)

- `_unregisterDirectoryIndex` is O(workspace) on every delete of an index file (`workspace.ts:185-212`) → keep per-directory candidate lists.
- `TextEdit.apply` builds a per-character array per edit (`text-edit.ts:22-50`) → offset-based slice concatenation.
- Per-node plugin dispatch re-enters a try/catch and probes 6 optional methods per AST node (`markdown-parser.ts:183-189`) → precompute the visitor list per parser.
- `getTagAtPosition` scans all tags × locations per call (`tag-edit.ts:265-283`) → per-URI index.
- CLI gets neither parser cache nor profiler (`foam-cli/src/support/filesystem.ts:172`) → wire both; big cold-start win for CLI/MCP and export.
- Profiler hygiene: no `reset()` (double-counts on second load), chars misreported as MiB (`load-profiler.ts:63-67`, `:147`, `:237`).

**Effort:** S-M per item · **Breaking:** No · **Impact:** Medium in aggregate.

### 3.7 (Strategic) Replace remark-parse v8 / unified v9 with micromark

The pinned parser stack is several majors behind. It is the root cause of: the regex-based footnote scan (`markdown-parser.ts:231-268`), the collapsed consecutive-footnote ASTs, likely the documented super-linear parse scaling, and the wikilink-in-math false positives (#1317). The bench file already ships an A/B harness for exactly this migration (`markdown-parser.bench.ts:97-101`).

**Proposal:** migrate to `micromark`/`mdast-util-from-markdown` behind the existing `ParserPlugin` seam; prove parity with the golden-file tests and the A/B bench before switching.

**Effort:** L · **Breaking:** Potentially (AST-shape-dependent plugins; parse edge cases change) · **Impact:** High long-term — removes a whole class of workarounds and the main super-linear cost; should be scheduled, not rushed.

---

## 4. Information model evolution

### 4.1 Make aliases participate in link resolution

Aliases are parsed (`markdown-parser.ts:700-712`), stored on `Resource`, offered by **link completion** (`link-completion.ts:269`) and search — but `listByIdentifier` (`workspace.ts:266-291`) only ever consults paths. `[[my-alias]]` yields a placeholder even when a note declares `alias: my-alias`: the system suggests links it then fails to resolve. This is the single biggest semantic gap in the model.

**Proposal:** index aliases alongside basenames with documented precedence (exact path > basename > alias), behind a config flag initially (matching the `directoryMode` precedent, `markdown-provider.ts:24`).

**Effort:** M · **Breaking:** Behaviorally (previously-broken links start resolving — flag-gated) · **Impact:** High — closes a visible feature contradiction; frequently expected by users coming from Obsidian.

### 4.2 Normalize placeholder identity in the model

`URI.placeholder(path)` does no normalization (`uri.ts:99-101`): `[[page-b]]` and `[../page-b.md]` denoting the same missing file become **two distinct graph nodes** (pinned in `graph.test.ts:225-260`), so the placeholders panel shows duplicates. Placeholder construction is scattered across four sites in `markdown-provider.ts` (`:120,132,152,167`), and "placeholder-ness" is modeled three different ways (URI scheme `uri.ts:201-203`; a phantom `Resource.type === 'placeholder'` that the workspace never stores; a template-trigger type).

**Proposal:** a single model-owned placeholder factory that canonicalizes identity (workspace-resolved path where resolvable, raw text kept as label); remove the phantom resource type or promote it to a real variant.

**Effort:** M · **Breaking:** Yes — placeholder paths are visible in `graph.placeholders`, the panel, and tests · **Impact:** Medium-High — correct placeholder dedup, simpler consumers, prerequisite for sane "create note from placeholder" flows.

### 4.3 Split `FoamWorkspace.find` and fix its inconsistencies

`find(URI | string)` (`workspace.ts:367-415`) is three functions behind one signature (trie get / identifier resolution / path probing across roots), and it returns the **stored object** normally but a **fresh shallow copy** when the reference carries a `#fragment` (`:408-413`) — reference equality depends on argument syntax. Ambiguity resolution ("alphabetically first path wins") is encoded in a sort call (`:290`).

**Proposal:** explicit `findByUri` / `findByIdentifier` / `findByPath`; fragment handling returns `{resource, section}` instead of a patched copy; document the ambiguity policy. Keep `find` as a deprecated shim for one release.

**Effort:** M · **Breaking:** Yes (widely used in foam-vscode; mechanical migration) · **Impact:** Medium — the API's biggest ambiguity source; enables §1.2's identifier inversion cleanly.

### 4.4 Key the graph by full URI identity, not `uri.path`

`links`/`backlinks`/`placeholders` are `Map<uri.path, …>` (`graph.ts:21-29, 247-258`): in a virtual workspace `file:///notes/a.md` and `vscode-vfs://github/notes/a.md` collide (multi-scheme resolution is explicitly supported — `workspace.test.ts:303-326`); fragments are silently ignored, so callers must remember `.asPlain()` (done in five places in `commands/links.ts`). The same path-keyed pattern recurs in the export context (`export/types.ts:179,184`) and embeddings (`ai/model/embeddings.ts:39`).

**Proposal:** introduce a small `URIMap<T>` (canonical `scheme://authority/path` keying, explicit fragment policy) in `model/uri.ts` and use it in graph, export, embeddings. Make `getLinks`/`getBacklinks` normalize their argument.

**Effort:** M · **Breaking:** Yes for direct readers of `graph.links`/`graph.backlinks` (public mutable maps — see §4.5) · **Impact:** Medium — correctness on virtual/multi-root workspaces (web extension, remote repos), removes a caller ritual.

### 4.5 Encapsulate the graph/tags collections

`graph.placeholders/links/backlinks` and `tags.tags` are `public readonly` Maps — the reference is readonly, the contents are not; any consumer can `foam.graph.links.clear()`. Stored `Resource`s are also held by reference with no copy (`workspace.ts:131`), so in-place mutation corrupts the index and defeats the `{old, new}` update diff.

**Proposal:** accessor methods returning `ReadonlyMap`/iterators; document (or enforce via `Object.freeze` in dev builds) that `Resource` is immutable once stored.

**Effort:** S-M · **Breaking:** Yes, mechanical · **Impact:** Medium — removes a foot-gun class; prerequisite for safely evolving internals (§4.4).

### 4.6 Batchable events with payloads

`workspace.clear()` fires one delete per resource (`workspace.ts:149-158`) → N graph mutations + N full tag rebuilds + N panel refreshes; there is no batch/transaction primitive even though `PauseableEmitter`/`EventBufferer` already exist (`common/event.ts:749, 878`). `graph.onDidUpdate` and `tags.onDidUpdate` are `Event<void>`, so all ~7 VS Code listeners can only blanket-refresh. Delivery is synchronous and re-entrant (`common/event.ts:706-733`).

**Proposal:** additive first — `onDidChangeBatch: Event<Change[]>` on the workspace, used by `clear()` and bulk load; a debounced aggregate `Foam.onDidChangeWorkspace` (the preview feature currently hand-rolls this from three subscriptions, `preview/index.ts:20-30`). Later, upgrade `onDidUpdate` to carry a delta (breaking for listeners).

**Effort:** M (additive) + S (listener migration) · **Breaking:** Additive now; delta payload later is breaking · **Impact:** Medium-High — turns O(N) panel refresh storms into O(1); foundation for scaling to large vaults.

### 4.7 Type-model tightening

- `Resource.type: string` → union `'note' | 'attachment' | 'image'` (`note.ts:146`); `properties: any` → `Record<string, unknown>` (`:147`). **Breaking**, mostly mechanical.
- `ResourceLink.definition?: string | NoteLinkDefinition` encodes a three-state machine decoded by four predicates with order-sensitive call sites (`note.ts:5-44`; `markdown-provider.ts:94-138`) → discriminated union `{kind: 'inline'} | {kind: 'ref-unresolved'; label} | {kind: 'ref-resolved'; definition}`. **Breaking** (parser + tests construct it).
- `Connection` (`graph.ts:8-12`) carries no resolution provenance → add `resolvedBy: 'path' | 'identifier' | 'directory-index' | 'placeholder'`; every consumer currently re-derives this. **Additive.** Also directly serves typed-links exploration (#1626).
- URI derivations (`getDirectory`, `joinPath`, …) preserve `fragment`/`query` (`uri.ts:125-152`), yielding directories with section anchors; `asPlain()` exists solely to undo it → drop fragment/query on parent/derivation ops. **Non-breaking in practice** (all call sites strip or have none).
- `asAbsoluteUri` (`uri.ts:465-493`) disagrees with `FoamWorkspace.resolveUri` on the primary case (`uri.test.ts:131-140` vs `workspace.test.ts:277-281`) and is publicly exported → redefine in terms of `resolveUri` or remove. **Breaking.**
- Dead indirection: `pathToPlaceholderId` is the identity function (`graph.ts:14`); `wikilinkPlugin.onDidVisitTree` is an empty function (`markdown-parser.ts:798-801`); duplicate `CancellationToken` in `progress.ts:21-24`. Delete. **Non-breaking.**

**Effort:** S-M per item · **Impact:** Medium — compile-time safety over runtime predicates; cheapest during the same release that takes §4.3/§4.4.

### 4.8 Parser instance isolation

`sectionStack` is module-level mutable state shared by every parser instance (`markdown-parser.ts:416`), and `onDidInitializeParser` mutates the module-level `unified` processor (`:63, :105`) so `extraPlugins` from one `createMarkdownParser` call leak into all others. Safe today only because parsing is synchronous and single-instance.

**Proposal:** per-instance processor; per-parse context object threaded through `ParserPlugin` (breaking for the plugin interface, which has few implementors).

**Effort:** M · **Breaking:** Yes (plugin interface) · **Impact:** Medium — prerequisite for embedded-note parsing, parallel parse, and the §3.7 migration.

---

## 5. API & package architecture

### 5.1 Tier and split the public API surface

`@foam/core` exposes a single 315-line barrel re-exporting **297 symbols**; cross-referencing all three in-repo consumers, **~102 are never imported by anyone**. Output is CJS-only, so importing `URI` drags in jexl, the export pipeline, and lint rules — the web bundle and MCP pay for subsystems they never call.

**Proposal:** add subpath exports (`@foam/core/model`, `/export`, `/query`, `/lint`) and ESM output alongside CJS; split the barrel into a documented contract tier and an internal tier; add an API-report CI check (api-extractor or attw). Root barrel should delegate to per-subsystem `index.ts` curators — today `src/index.ts:194-239` hand-duplicates `export/index.ts`'s list and the two have already diverged.

**Effort:** M-L · **Breaking:** Additive now; demoting unused symbols is breaking for hypothetical external users only · **Impact:** High — bundle size for web/MCP, and it establishes the semver contract *before* external consumers depend on accidental surface.

### 5.2 Move host concerns out of core

- The App Insights connection string and envelope builder live in the platform-agnostic core (`telemetry.ts:158-159`, exported at `index.ts:180-184`). The string is deliberately a non-secret ingestion key, but a product's telemetry destination is deployment config, not library code — any fork/embedder silently inherits Foam's endpoint.
- `IFoamConfig` (`config.ts:1-46`) carries ≥8 editor-UI getters (`getGraphOnStartup`, `getPreviewEmbedNoteType`, `getCompletionLabel`, …) that a headless CLI is forced to stub (`foam-cli/src/support/config.ts:60-65`).
- `Config` is a mutable process-global singleton (`config.ts:149-166`) with exactly one core reader (`template-discovery.ts:15`) — a real hazard for `@foam/mcp`, which is meant to be embeddable (two workspaces in one process can't differ).

**Proposal:** core keeps `ITelemetryReporter` + bucketing only; endpoint + consent copy move to hosts. Split `CoreConfig` (files, templates, daily notes) from host config. Thread config explicitly (`getTemplatesDir(rootUri, config)`), retire the global.

**Effort:** M · **Breaking:** Yes — small, in-repo call-site count (≤5) · **Impact:** Medium-High — makes core genuinely embeddable and forkable; unblocks publishing `@foam/mcp`.

### 5.3 Retire the `foam-vscode` shim layer; repatriate stranded platform-agnostic code

Four directories in `foam-vscode/src` have zero `vscode` imports: `src/core/` (a second `bootstrap` whose 8th positional parameter *diverges* from core's — `foam-vscode/src/core/model/foam.ts:23-32` vs `foam.ts:32-42`, an accident waiting to happen), `src/ai/model` + `src/ai/services` (382-line `FoamEmbeddings`, pure core), `src/lint/`, and `src/daily-note/`. The shim type also makes the feature registry contravariantly unsound — it only compiles because `strict: false`.

The lint case is user-visible: the four wikilink rules (`rule-check-links.ts:22`) are only reachable by the editor, so **`foam lint` in CI cannot catch broken wikilinks** while the editor can (`foam-cli/src/commands/lint.ts:14-18`). Relatedly, `lintNote` hardcodes its rule list while `lintWorkspace` takes `rules[]` (`lint.ts:47-49, 86`) — two extensibility models in one file.

**Proposal:** move embeddings/lint/daily-note logic into core (embeddings as an optional `Foam` member; Ollama provider stays host-side); make core's `bootstrap` take an options object (it has **nine positional parameters**); delete the shim. Align `lintNote`/`lintWorkspace` on injected rules + `defaultLintRules()`.

**Effort:** M-L · **Breaking:** `bootstrap` and `lintNote` signatures (3 and 2 call sites); rest is internal moves · **Impact:** High — one `bootstrap`, CLI lint parity (CI catches broken wikilinks), and unlocks `strict: true` for the extension.

### 5.4 Unify the CLI/MCP wire format

`foam-cli/src/support/serializers.ts` (148 lines) and `foam-mcp/src/serializers.ts` (203 lines) independently serialize the same nine core result types — and disagree: CLI emits absolute fs paths (`serializers.ts:45`), MCP emits workspace-relative POSIX paths with `placeholder:<id>` handling (`serializers.ts:52-55`). Same note, two encodings; CLI has no placeholder story at all.

**Proposal:** one `@foam/core/serialize` module owning the `Json*` types and URI encoding (option: `'fs' | 'workspace-relative'`); both hosts consume it. Prefer unifying on workspace-relative.

**Effort:** M · **Breaking:** CLI JSON output changes if unified (recommended; flag the old encoding) · **Impact:** Medium — consistency for scripts/agents consuming both surfaces; halves maintenance.

### 5.5 Honor the `IDataStore` contract; make capabilities explicit

The interface requires `list(pattern)` to filter (`datastore.ts:12-17`) but the VS Code implementation ignores the pattern entirely (`editor.ts:408` takes no parameter) — currently masked only because saved queries build their own store (`saved-store.ts:102-138`); any future `dataStore.list(glob)` call in the extension is a silent data bug. `GenericDataStore` also throws at runtime for the 4-of-6 optional operations while claiming the full interface (`datastore.ts:117-143`), and `read` conflates missing vs unreadable (both `null`, `:106-115`). None of the shipping implementations have direct tests.

**Proposal:** fix the VS Code `listFiles` to honor the glob; split `IReadableDataStore`/`IWritableDataStore` (or a capabilities probe); distinguish not-found from error; add the missing tests.

**Effort:** M · **Breaking:** Interface split is breaking (4 implementations, all in-repo) · **Impact:** Medium — closes a documented contract violation before it becomes a bug.

### 5.6 Packaging hygiene (batch)

- `@foam/core/test` relative-imports `../src/*`, forcing a dual-instance-of-`URI` alias hack in **three** vitest configs (`foam-vscode/vitest.config.mts:41-48` documents it), while `instanceof URI` is used in production (`convert-links-format.ts:26`); `test-utils` also imports `micromatch`, which is not a declared dependency, and there's no `files` allowlist so npm ships `src/`, `test-data/`, etc. → import via the package entry, fix deps, add `files`.
- `foam-vscode` duplicates 15 of core's dependencies as phantom runtime `dependencies` (nothing installs them; esbuild bundles) — version skew between the two `package.json`s would silently ship a different parser than tests run → move to `devDependencies`, single source of truth in core.
- `@foam/mcp` declares `"@foam/core": "*"` as a runtime dep, but core publishes under the name `foam-core` (`release.js:29-31`) — the moment `@foam/mcp` is published it cannot resolve → bundle like cli/vscode, or publish under the real name.
- Dead `cli` build target in `foam-vscode/esbuild.js:31,136-146,177-188` (the `src/cli/` it builds no longer exists) → delete.
- Three field-identical graph-data types (`graph-data-builder.ts:5-16`, `export/types.ts:126-144`, `foam-graph/src/protocol.ts:16-25`), with `build-site-graph.ts:12` compiling only by structural coincidence → alias the two in-core copies; keep the protocol copy as a deliberate wire contract with a compile-time compatibility assertion.
- `graph-data-builder.ts:75` ships the **entire raw frontmatter** into graph payloads consumed by the webview *and the published static site* — private frontmatter fields leak into published graph JSON → allowlist exported keys.

**Effort:** S-M per item · **Breaking:** No (except the frontmatter allowlist, a behavior fix) · **Impact:** Medium — the frontmatter leak in particular is a privacy fix for publishing.

---

## 6. Platform integrity (web / CLI parity)

### 6.1 Mechanically enforce "no Node imports in foam-core"

The invariant holds today by review only: core's `tsconfig` includes `"types": ["node"]`, so `process`/`Buffer` type-check fine. One lint rule (`no-restricted-imports` on `fs|path|os|node:*` in `packages/foam-core/src`) makes the repo's most important invariant enforceable.

**Effort:** S · **Breaking:** No · **Impact:** High leverage for the cost — prevents an entire regression class.

### 6.2 `export-html-page` ships broken in the web extension

It imports `fs/promises` directly (`export-html-page/index.ts:2,85,91`) and is registered unconditionally; the web build's `polyfillNode()` makes it *bundle* but not work. Two other fs-users get bespoke esbuild `onResolve` swaps (`esbuild.js:72-101`) — a substring-matching mechanism invisible from the source tree.

**Proposal:** route file I/O through `foam.services.dataStore` (already works in both hosts); replace the regex swap mechanism with explicit `.web.ts` twins or `browser` field mapping; use §2.2's `supports` field to gate genuinely Node-only features.

**Effort:** S (gate) + M (dataStore refactor) · **Breaking:** No · **Impact:** Medium — a visibly broken command in the web host today.

### 6.3 Path-string discipline cleanup

Per the repo's own URI convention: `grouped-resources-tree-data-provider.ts:1,85-89` runs Node `path.parse` on a URI component; `export/types.ts:72` accepts `contentRoot?: string | URI` (the one both-typed field in core's config surface — a `vscode-vfs://` workspace will resolve incorrectly); `foam-cli/src/support/filesystem.ts:28-34` reimplements core's `isWithinPath` under the same name with a different signature. Also export `getBasename`/`getExtension`/`getDirectory` from core's barrel — CLAUDE.md tells contributors to use them, but they aren't currently exported (`index.ts:151-158`), which is part of why reimplementations happen.

**Effort:** S · **Breaking:** `contentRoot: URI` only (2 in-repo call sites) · **Impact:** Low-Medium each; collectively keeps the convention honest.

---

## 7. Documentation

### 7.1 `CLAUDE.md` describes the pre-`foam-core` repository and actively misdirects

It states core lives in `packages/foam-vscode/src/core/` (now a one-file shim), features in `src/features/` (now `src/vscode/features/`), claims a `tsconfig` `paths` mapping for `@foam/graph-view` that doesn't exist, and recommends path utilities core doesn't export. `CONTRIBUTING.md:58-62` is *correct*, so the two root docs contradict each other. Also: `docs/user/features/templates.md:284` links to a moved file (user-facing broken link), and `docs/dev/testing-conventions.md:25` is stale.

**Proposal:** rewrite the structural sections of `CLAUDE.md` against the current tree and make it point to `CONTRIBUTING.md` for structure (the duplication is what drifted); fix the two stale doc links.

**Effort:** S · **Breaking:** No · **Impact:** High for contributor/agent effectiveness — this file is loaded into every AI-assisted session and currently sends it to the wrong directories.

---

## Prioritized roadmap

**Phase 1 — Correctness & leaks (all non-breaking; ~2 weeks)**
1.1 trie case collision · 1.2 incremental-add divergence · 1.3 edit corruption · 1.5 tag ranges · 1.6 small-fix batch · 2.1–2.4 lifecycle fixes · 5.6 frontmatter leak in published graphs · 6.1 core import lint · 7.1 CLAUDE.md rewrite

**Phase 2 — Performance (non-breaking; ~1–2 weeks; verified by the existing perf gate)**
3.1 block-parser walk · 3.3 matcher Set (+#1388 gitignore) · 3.2 cache-hit cost · 3.6 mechanical batch · 3.4 incremental tags · 3.5 rename overlay

**Phase 3 — Parity & packaging (mostly non-breaking; ~2 weeks)**
5.3 lint rules to core (CLI wikilink lint) · 1.4 CLI markdown-link rename · 6.2 web export fix + feature `supports` · 5.4 shared serializers · 5.6 packaging batch · 4.6 batch events (additive part) · 2.2 feature isolation + ids

**Phase 4 — Model & API evolution (breaking; one coordinated minor/major)**
4.1 alias resolution (flagged) · 4.2 placeholder identity · 4.3 `find` split · 4.4 `URIMap` graph keying · 4.5 collection encapsulation · 4.7 type tightening · 4.8 parser isolation · 5.1 API tiering + subpaths · 5.2 config/telemetry out of core · 5.5 datastore contract · **then** 3.7 micromark migration behind the A/B bench

**Issue cross-references:** #1375/#1689 (Phases 2, 4-parser), #1388 (3.3), #1240 (1.5/4.7 groundwork), #1317 + #1631 (3.7), #1626 (Connection provenance, 4.7), #1685 (safe to do alongside 3.2), #1303 (1.1 closes the remaining gap).

---

### Dev Design Improved Static Site Generation (`docs/dev/design/improved-static-site-generation.md`)

# Improved Static Site Generation

## Summary

Foam should adopt a two-layer publishing architecture:

- a Foam-owned publishing layer in TypeScript that understands Foam semantics
- a modern static site shell, with Astro and Starlight as the default implementation

This keeps Foam aligned with the project's build-vs-assemble principle while still giving users a polished website for browsing their knowledge base.

## Problem

Today, Foam has publishing documentation and community templates, but not a single modern architecture that:

- preserves Foam semantics reliably
- produces a high-quality static site
- gives the project a durable TypeScript integration point
- remains optional instead of locking Foam to one publishing target

If Foam only chooses a website framework, the framework ends up becoming the architecture. That is too brittle. Foam needs a publishing pipeline of its own.

## Goals

- Publish a Foam knowledge base as a static website
- Preserve Foam-specific semantics where possible:
  - wikilinks
  - aliases
  - block anchors and section links
  - embeds
  - tags
  - backlinks
  - graph metadata
  - publish visibility rules
  - `foam-query` blocks, at least where they can be resolved safely at build time
- Reuse Foam parsing and graph logic
- Keep the publishing path framework-agnostic enough to support other site targets later
- Make the default user experience modern and visually strong

## Non-Goals

- Building a bespoke all-in-one site generator as the first step
- Replacing ordinary Markdown authoring with a new required syntax
- Requiring VS Code APIs during website generation
- Solving every interactive publishing feature in the first iteration

## Recommended Stack

### Default Site Stack

- Framework: Astro
- Site shell: Starlight
- Content input: generated Markdown plus derived JSON metadata
- Optional richer authored pages: Markdoc or MDX where needed

### Why This Stack

Astro and Starlight provide the polished site quickly. Foam's own publishing layer protects the project from tying note semantics directly to any one site framework.

This means Foam can:

- ship a good default website
- keep the core publishing logic in TypeScript
- preserve the option to support other renderers later

## Proposed Architecture

## 1. Foam Publishing Layer

Add a publishing layer responsible for turning a Foam workspace into publishable artifacts.

The logical module should not depend on VS Code. It should consume Foam core models and services.

For implementation, this should be phased:

- first iteration: `packages/foam-vscode/src/publish`
- later extraction: `packages/foam-publish`

The first iteration should be written as if it were already an extractable package. That means keeping it framework-agnostic, avoiding `vscode` imports, and giving it a clean entrypoint and module structure.

Suggested responsibilities:

- discover and load publishable notes from a workspace
- resolve wikilinks, aliases, and anchors using Foam's own workspace and graph logic
- evaluate publish visibility rules
- rewrite links for the target site
- expand or rewrite embeds
- compute backlinks
- compute graph/search metadata
- render or precompute `foam-query` output when possible
- emit a normalized set of output files for a site framework

Suggested inputs:

- workspace root
- publish target configuration
- output mode and path

Suggested outputs:

- transformed Markdown files for each published note
- JSON indexes for search, backlinks, graph, and route metadata
- copied static assets and attachments

## 2. Starlight Target

Add a Starlight target inside the Foam publishing layer that materializes a runnable site directory.

Responsibilities:

- render the transformed notes into a Starlight-compatible content tree
- write the site scaffold needed to run Astro and Starlight in the output directory
- provide navigation, layout, SEO, and search UI through the generated Starlight app
- keep Foam-specific semantics in the publish layer rather than in the site framework

This target should stay thin. It is an implementation of the publishing output, not the source of truth for Foam semantics.

## 3. CLI and Automation

Expose the pipeline through a CLI entry point, likely via Foam CLI or a dedicated command.

Examples:

- build a local static site
- watch and rebuild during development
- emit publishable artifacts for GitHub Pages, Vercel, or Netlify

This matches the existing direction in the repository toward build-time transformations and automation.

## Data Flow

The first version should follow this pipeline:

1. Read the Foam workspace using core services
2. Filter notes according to publish rules
3. Parse notes and resolve Foam constructs
4. Emit transformed Markdown for the site
5. Emit derived JSON indexes
6. Let the generated Astro and Starlight site build the final static HTML

In shorthand:

`Foam workspace -> foam-publish -> Markdown + JSON -> Astro/Starlight -> static HTML`

## Why Generated Markdown Plus JSON

This is the most practical first output format.

Advantages:

- It keeps the content inspectable and portable
- It works naturally with Starlight and Astro content collections
- It avoids forcing the site layer to reimplement Foam parsing logic
- It gives the site enough structured metadata for backlinks, graph views, and search-related UI

Generating only HTML would make customization harder. Generating only a raw graph JSON model would push too much work into the site layer. Markdown plus derived JSON is the right balance.

## Treatment of Foam Features

## Wikilinks and Aliases

Resolve them at build time to stable site routes. The site should not need to guess how Foam resolution works.

## Block Anchors and Section Links

Emit stable heading and block IDs during transformation so links and popovers can target exact content.

## Embeds

Handle note embeds at build time where possible. Preserve attachment embeds and image references as normal site assets.

## Backlinks

Compute backlinks in `foam-publish` and expose them as page metadata or a site-wide index.

## Graph View

Emit graph data as JSON derived from Foam's own graph model. Render it in the site layer with a dedicated component.

## `foam-query`

Treat query blocks as build-time features when safe and deterministic. Where execution is unsafe or unsupported, fail clearly and leave a readable placeholder in output.

## Publish Visibility Rules

Implement this in `foam-publish`, not in the site layer. The site should only receive already-filtered content.

## Why Not Make Markdoc the Core

Markdoc is a good integration option, but not a good center of gravity for the first version.

Reasons:

- Foam notes should stay ordinary Markdown first
- Foam already has its own semantics to preserve
- switching the base representation to Markdoc would increase coupling and reduce portability

Markdoc is still useful for richer authored documentation pages outside the imported note corpus.

## Why Not Start With Quartz

Quartz is close enough to Foam that it is worth studying and possibly spiking against. However, starting directly from Quartz would blur the boundary between Foam semantics and site implementation.

The project should instead:

- borrow feature ideas from Quartz
- compare experience against Quartz during prototyping
- keep Foam's publishing logic separate from the chosen renderer

## Incremental Delivery Plan

### Phase 0: Internal Publish Spike

- Implement the publishing layer in `packages/foam-vscode/src/publish`
- Reuse existing Foam core and parser code where possible
- Keep the module free of `vscode` imports
- Prove the basic API and output shape before extracting a standalone package

### Phase 1: Minimal Viable Site

- Publish filtered notes as routed pages
- Rewrite wikilinks and attachments
- Generate navigation from folders and titles
- Support search through the default Starlight capabilities or a simple generated index

### Phase 2: Foam Semantics

- Add backlinks
- Add block anchors and section-deep links
- Add note embeds
- Add publish rules

### Phase 3: Knowledge-Base Experience

- Add graph view
- Add hover previews
- Add richer query rendering
- Add deployment presets and starter templates

## Open Questions

- What exact publish-rule syntax should Foam support: public-by-default, private-by-default, or folder-based publishing?
- Should `foam-query-js` be supported in published output at all, or only the declarative query language?
- Should the first version generate files directly into a site workspace, or into an intermediate output folder consumed by the site package?
- How much of the existing preview pipeline can be shared directly, and how much should move into framework-agnostic publish utilities?

## Proposed Decision

Adopt Astro plus Starlight as the default website stack, and implement a framework-agnostic Foam publishing layer that emits transformed Markdown and derived JSON for the site to render.

Start that implementation in `packages/foam-vscode/src/publish`, then extract it to `packages/foam-publish` once the API and boundaries have stabilized.

That gives Foam the right default without collapsing publishing strategy into a single website framework.

---

### Dev Design Static Site Publishing Research (`docs/dev/design/static-site-publishing-research.md`)

# Static Site Publishing Research

Researched on April 17, 2026.

## Context

Foam already has a publishing story, but it is spread across older templates and partial proposals rather than a single modern architecture.

Relevant existing material in this repository:

- [Publishing pages](../../user/publishing/publishing.md) says Foam should remain valid Markdown and be publishable by many tools, while leaving room for a more Foam-aware publishing path later.
- Improved static-site generation, search in published workspaces, graph in published workspaces, and publishing permissions are all established goals.

That gives a fairly clear constraint set:

- Published output should preserve Foam semantics such as wikilinks, aliases, embeds, block anchors, backlinks, and queries where practical.
- The publishing path should stay optional. A Foam workspace should still be usable as normal Markdown without requiring a bespoke site generator.
- The implementation should fit a TypeScript-heavy codebase and reuse Foam's parsing and graph logic instead of reimplementing it in another stack.

## Evaluation Criteria

The tools were evaluated against these criteria:

- Quality of the generated site for documentation and knowledge-base content
- Ease of integrating Foam-specific behavior
- TypeScript support and extensibility
- Static output and deployment simplicity
- Suitability for a navigable knowledge base rather than only linear product docs

## What Obsidian Publish Gets Right

Obsidian Publish is the product benchmark, not the implementation benchmark.

Its public positioning emphasizes the reader experience for connected notes: hover previews, graph view, stacked navigation, backlinks, strong SEO, mobile support, and easy customization. Those are the right north-star features for Foam publishing even if Foam should not copy the hosted-product model.

Source:

- [Obsidian Publish](https://obsidian.md/publish)

## Option Review

## Astro

Astro is a strong foundation layer for Foam publishing.

Why it fits:

- It is modern, fast, and static-first.
- It has first-class TypeScript support.
- It supports Markdown and MDX directly.
- It has clear extension points through remark and rehype plugins.
- It has typed content collections that work well for structured frontmatter and derived metadata.

Most importantly, Astro is a good host for a Foam publishing adapter. It does not force Foam to adopt a new authoring model just to get a good site.

Sources:

- [Astro Markdown](https://docs.astro.build/en/guides/markdown-content/)
- [Astro Content Collections](https://docs.astro.build/en/guides/content-collections/)

## Starlight

Starlight is the strongest out-of-the-box shell among the options reviewed.

Why it stands out:

- It produces polished documentation sites quickly.
- It includes site navigation, search, SEO, internationalization, readable typography, code highlighting, and dark mode out of the box.
- It supports Markdown, Markdoc, and MDX.
- It adds frontmatter validation with TypeScript type safety.
- It keeps access to the wider Astro ecosystem instead of boxing the project into a narrow template.

For Foam, this means the team can spend effort on Foam behavior instead of rebuilding the surrounding documentation-site basics.

Source:

- [Starlight](https://starlight.astro.build/)

## Markdoc

Markdoc is powerful, but it should not be the center of Foam's publishing architecture.

It is a good option for adding structured, component-rich authoring to specific parts of a site. However, using Markdoc as the canonical representation of Foam notes would move Foam away from portable Markdown and toward a richer custom syntax. That tradeoff does not look justified for the first version.

Markdoc is best treated as an optional layer for advanced authored pages, not as the base representation of the knowledge base itself.

Sources:

- [Markdoc](https://markdoc.dev/)
- [Astro Markdoc integration](https://docs.astro.build/en/guides/integrations-guide/markdoc/)

## Quartz

Quartz is the closest match to Foam's use case and should be treated as the main reference implementation.

Why it matters:

- It is explicitly oriented toward note graphs and digital gardens.
- It is configured in TypeScript.
- It exposes a plugin pipeline with transformers, filters, and emitters.
- It already supports popover previews, backlinks, graph view, explorer navigation, and full-text search.
- It includes an `ObsidianFlavoredMarkdown` plugin, which shows direct alignment with the knowledge-base space.

Quartz is compelling enough that it could be used for a fast proof of concept. The reason not to pick it as the primary foundation is not quality; it is control over architecture. Foam still needs a publishing layer for features like `foam-query`, publish permissions, and reuse of Foam core models. Once that layer exists, Astro and Starlight provide a cleaner long-term substrate for a broader website experience.

Sources:

- [Quartz Configuration](https://quartz.jzhao.xyz/configuration)
- [Quartz Explorer](https://quartz.jzhao.xyz/features/explorer)
- [Quartz Graph View](https://quartz.jzhao.xyz/features/graph-view)
- [Quartz Backlinks](https://quartz.jzhao.xyz/features/backlinks)
- [Quartz Popover Previews](https://quartz.jzhao.xyz/features/popover-previews)

## Docusaurus

Docusaurus is a capable modern documentation platform, but it does not look like the best fit for Foam's first publishing path.

It has strong support for search, versioning, internationalization, MDX, and theme customization. The issue is fit rather than capability: it is more naturally shaped for product documentation than for a wiki-like knowledge base with Foam-specific semantics.

It remains a viable option for projects that want a more React-centric docs platform, but it is not the best default recommendation for Foam.

Source:

- [Docusaurus Documentation](https://docusaurus.io/docs)

## Recommendation

The recommended direction is:

1. Use Astro as the web framework.
2. Use Starlight as the website shell.
3. Build a Foam-specific publishing layer in TypeScript.
4. Keep Markdoc optional.
5. Use Quartz as a reference point and comparison target, especially for graph, popover, backlinks, and navigation behavior.

This direction gives Foam a modern, polished static site without forcing Foam to become a site generator.

## Main Architectural Takeaway

The core design problem is not choosing a renderer. The core design problem is preserving Foam semantics on the web.

That implies a separation of concerns:

- Foam should own parsing, graph resolution, publish filtering, and content transformation.
- The site framework should own rendering, navigation chrome, styling, and deployment ergonomics.

That boundary is what the architecture note should lock down.

---

### User Features Backlinking (`docs/user/features/backlinking.md`)

# Backlinks

Backlinks are one of Foam's most powerful features for knowledge discovery. They automatically show you which notes reference your current note, creating a web of interconnected knowledge that reveals surprising relationships between your ideas.

_[📹 Watch: Understanding and using backlinks in Foam]_

## What Are Backlinks?

A backlink is a connection from another note that points to the note you're currently viewing. While you create forward links intentionally with `[[wikilinks]]`, backlinks are discovered automatically by Foam.

### Forward Links vs. Backlinks

**Forward Links** (what you create):

```markdown
# Machine Learning Note

I'm studying [[Neural Networks]] and [[Deep Learning]] concepts.
```

**Backlinks** (what Foam discovers):
If you're viewing the "Neural Networks" note, Foam shows you that "Machine Learning Note" links to it, even though you didn't explicitly create that reverse connection.

This bidirectional linking creates a richer knowledge network than traditional hierarchical folders.

## Accessing Backlinks - Connections Panel

The Connections panel shows both forward links and backlinks:

1. **Open Command Palette** (`Ctrl+Shift+P` / `Cmd+Shift+P`)
2. **Type "connections"** and select "Explorer: Focus on Connections"
3. **Use the filter buttons** to show only backlinks, forward links, or all connections

_[📹 Watch: Finding and opening the backlinks panel]_

## Using Backlinks for Knowledge Discovery

### 1. Finding Unexpected Connections

Backlinks often reveal relationships you didn't consciously create:

**Example:** While reviewing a "Productivity" note, backlinks might show connections from:

- A cooking recipe (time management for meal prep)
- A fitness routine (efficient workout planning)
- A work project (team productivity strategies)

These diverse connections can spark new insights and cross-domain learning.

### 2. Identifying Important Concepts

Notes with many backlinks are often central to your thinking:

- **Hub concepts** that connect many ideas
- **Frequently referenced** resources or definitions
- **Bridge topics** that span multiple domains

### 3. Building Context Around Ideas

Backlinks provide context for how you use concepts across different areas:

- How you apply the same principle in various projects
- Evolution of your thinking about a topic over time
- Different perspectives you've encountered on the same idea

_[📹 Watch: Using backlinks for knowledge discovery and research]_

---

### User Features Block Anchors (`docs/user/features/block-anchors.md`)

# Block Anchors

Block anchors let you link to a specific paragraph, list item, heading, or blockquote within a note — not just to the note as a whole or to a section heading.

## Adding a Block Anchor

Place `^your-id` at the end of any block element. The ID can contain letters, numbers, and hyphens.

The `^id` marker is hidden in the preview — it's metadata, not visible text.

### Paragraph

```markdown
This is an important finding from the experiment. ^key-finding
```

Multi-line paragraphs work too — put the anchor at the end of the last line:

```markdown
The first measurements were inconclusive.
After repeating the experiment, results became clear. ^experiment-result
```

### List item

Place the anchor at the end of the item text. Foam anchors the entire item, including any sub-items:

```markdown
- Mix dry ingredients thoroughly ^dry-step
  - 2 cups flour
  - 1 tsp salt
- Add wet ingredients ^wet-step
```

To anchor an entire list, place `^id` on its own line immediately after the last item (no blank line):

```markdown
- First item
- Second item
- Third item
^shopping-list
```

### Heading

```markdown
## Methodology ^methodology
```

The anchor applies to the heading line itself, not the entire section below it.

### Blockquote

Three placements are supported:

**As the last line inside the blockquote:**

```markdown
> The only way to do great work is to love what you do.
> ^jobs-quote
```

**On its own line immediately after the blockquote:**

```markdown
> We shall fight on the beaches,
> we shall fight on the landing grounds.
^churchill-beaches
```

**After the blockquote with a blank line** (useful if your markdown formatter inserts one):

```markdown
> We shall fight on the beaches,
> we shall fight on the landing grounds.

^churchill-beaches
```

### Code block

Place `^id` on its own line after the closing fence. One blank line between the fence and `^id` is also accepted (useful if your markdown formatter adds one automatically):

````markdown
```python
def greet(name):
    return f"Hello, {name}"
```
^greet-function
````

### Table

Place `^id` on its own line after the table. One blank line is also accepted:

```markdown
| Name  | Score |
| ----- | ----- |
| Alice | 95    |
| Bob   | 87    |
^results-table
```

## Linking to a Block

Use `[[note-name#^blockid]]` to link directly to a block:

```markdown
[[research-notes#^key-insight]]
[[research-notes#^list-ref]]
```

Foam provides autocomplete for block IDs when you type `#^` inside a wikilink.

You can also add display text:

```markdown
[[research-notes#^key-insight|See the key insight]]
```

## Embedding a Block

Use `![[note-name#^blockid]]` to embed just that block inline:

```markdown
![[research-notes#^key-insight]]
```

Only the referenced block's content is shown — not the entire note.

## Renaming a Block ID

Place your cursor on a `^blockid` anchor and press `F2` to rename it. Foam updates the anchor and all wikilinks that reference it across your workspace.

## Diagnostics

Foam warns you when a block link points to a `^id` that doesn't exist in the target note. A quick-fix lets you pick from the available block IDs.

If you accidentally use the same `^id` twice in one file, Foam flags the duplicate with a warning. A quick-fix replaces it with a freshly generated unique ID.

## Related

- [[wikilinks]] - General linking
- [[footnotes]] - Adding references and side notes
- [[embeds]] - Embedding notes and blocks

[wikilinks]: wikilinks.md "Wikilinks"
[footnotes]: footnotes.md "Footnotes"
[embeds]: embeds.md "Note Embeds"

---

### User Features Commands (`docs/user/features/commands.md`)

# Foam Commands

Foam has various commands that you can explore by calling the command palette and typing "Foam".

In particular, some commands can be very customizable and can help with custom workflows and use cases.

## foam-vscode.create-note command

This command creates a note.
Although it works fine on its own, it can be customized to achieve various use cases.
Here are the settings available for the command:

- `notePath`: The path of the note to create. If relative it will be resolved against the workspace root.
- `templatePath`: The path of the template to use. If relative it will be resolved against the workspace root.
- `title`: The title of the note (that is, the `FOAM_TITLE` variable)
- `text`: The text to use for the note. If also a template is provided, the template has precedence
- `variables`: Variables to use in the text or template
- `date`: The date used to resolve the FOAM*DATE*\* variables. in `YYYY-MM-DD` format
- `onFileExists?: 'overwrite' | 'open' | 'ask' | 'cancel'`: What to do in case the target file already exists

To customize a command and associate a key binding to it, open the key binding settings and add the appropriate configuration, here are some examples:

- Create a note called `test note.md` with some text. If the note already exists, ask for a new name

```
{
  "key": "alt+f",
  "command": "foam-vscode.create-note",
  "args": {
    "text": "test note ${FOAM_DATE_YEAR}",
    "notePath": "test note.md",
    "onFileExists": "ask"
  }
}
```

- Create a note following the `weekly-note.md` template. If the note already exists, open it

```
{
  "key": "alt+g",
  "command": "foam-vscode.create-note",
  "args": {
    "templatePath": ".foam/templates/weekly-note.md",
    "onFileExists": "open"
  }
}
```

## foam-vscode.open-resource command

This command opens a resource.

Normally it receives a `URI`, which identifies the resource to open.

It is also possible to pass in a filter, which will be run against the workspace resources to find one or more matches.

- If there is one match, it will be opened
- If there is more than one match, a quick pick will show up allowing the user to select the desired resource

Examples:

```
{
  "key": "alt+f",
  "command": "foam-vscode.open-resource",
  "args": {
    "filter": {
      "title": "Weekly Note*"
    }
  }
}
```

## Link Conversion Commands

Foam provides commands to convert between wikilink and markdown link formats.

### foam-vscode.convert-wikilink-to-mdlink

Converts a wikilink at the cursor position to markdown link format with a relative path.

Example: `[[my-note]]` → `[My Note](../path/to/my-note.md)`

### foam-vscode.convert-mdlink-to-wikilink

Converts a markdown link at the cursor position to wikilink format.

Example: `[My Note](../path/to/my-note.md)` → `[[my-note]]`

**Usage:**

1. Place your cursor inside a wikilink or markdown link
2. Open the command palette (`Ctrl+Shift+P` / `Cmd+Shift+P`)
3. Type "Foam: Convert" and select the desired conversion command

---

### User Features Custom Markdown Preview Styles (`docs/user/features/custom-markdown-preview-styles.md`)

# Custom Markdown Preview Styles

Visual Studio Code allows you to use your own CSS in the Markdown preview tab.

## Instructions

Custom CSS for the Markdown preview can be implemented by using the `"markdown.styles": []` setting in `settings.json`. The stylesheets can either be https URLs or relative paths to local files in the current workspace.

For example, to load a stylesheet called `Style.css`, we can update `settings.json` with the following line:

```
{
  "markdown.styles": ["Style.css"]
}
```

## Foam elements

### Foam note & placeholder links

It is possible to custom style the links to a note or placeholder. The links are an `<a>` tag. For notes use the class `foam-note-link`, for placeholders use `foam-placeholder-link`.

### Cyclic inclusion warnings

Foams offers the functionality to include other notes in your note. This will be displayed in the preview tab. Foam recognises a cyclic inclusion of notes and will display a warning when detected. The following html is used and can be custom styled using the class `foam-cyclic-link-warning`.

```html
<div class="foam-cyclic-link-warning">
  Cyclic link detected for wikilink: ${wikilink}
</div>
```

---

### User Features Custom Snippets (`docs/user/features/custom-snippets.md`)

# Adding Custom Snippets

You can add custom snippets whilst the default set of snippets are decided by following the below steps:

1. `Cmd` + `Shift` + `P` (`Ctrl` + `Shift` + `P` for Windows), type `snippets` and select `Preferences: Configure User Snippets`.
2. The command palette will remain in focus. Search for `markdown` and select the entry entitled `markdown.json (Markdown)`.
3. A JSON file will open. You can author your own snippets using the [documentation](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_create-your-own-snippets) to help you, or if you're using a snippet shared by another Foam user then you can copy and paste it in, as the below GIF demonstrates:
   

To get started, you might consider replacing the entire contents of the `markdown.json` file opened by the steps above with the JSON in [this comment](https://github.com/foambubble/foam/pull/192#issuecomment-666736270).

---

### User Features Daily Notes (`docs/user/features/daily-notes.md`)

# Daily Notes

Daily notes allow you to quickly create and access a note file for each day.

## Creating Daily Notes

- **Command:** `Ctrl+Shift+P` → "Foam: Open Daily Note"
- **Shortcut:** `Alt+D`
- **Snippets:** Type `/today`, `/yesterday`, `/tomorrow` in any note

## Automatic Daily Notes

Open daily note automatically on VS Code startup:

```json
{
  "foam.openDailyNote.onStartup": true
}
```

## Daily Note Templates

Create `.foam/templates/daily-note.md` to customize the structure:

```markdown
---
type: daily-note
---

# Daily Note - $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE

## Tasks

- [ ]

## Notes
```

## Linking to the Previous Daily Note

`$FOAM_PREVIOUS_DAILY_NOTE` expands to the most recent daily note that exists before the one being created. It skips gaps, so after a weekend or a holiday it points at the last note you actually wrote — unlike `/yesterday`, which is always the calendar day before.

```markdown
---
type: daily-note
---

# $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE

Previously: [[$FOAM_PREVIOUS_DAILY_NOTE]]
```

In your very first daily note there is no previous one, and the variable expands to nothing. To write something else instead, give it a fallback:

```markdown
Previously: ${FOAM_PREVIOUS_DAILY_NOTE:nothing yet}
```

The variable is only available in the daily note template, and it finds daily notes by matching the path your template creates them at. That path has to spell out the year, month and day in numbers — `/journal/$FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE.md` works, and so does `$FOAM_TITLE`. A path built from a month name or a week number (`$FOAM_DATE_MONTH_NAME`, `$FOAM_DATE_WEEK`) cannot be read back, so the variable stays empty and its fallback shows instead. Daily notes written before you last changed that path are not found either. A JavaScript daily note template picks its path as it runs, so the variable is empty there too — a JavaScript template can find the previous note itself.

## Date Snippets

Create links to recent daily notes using snippets:

| Snippet      | Date          |
| ------------ | ------------- |
| `/today`     | today         |
| `/tomorrow`  | tomorrow      |
| `/yesterday` | yesterday     |
| `/monday`    | next Monday   |
| `/+1d`       | tomorrow      |
| `/-3d`       | 3 days ago    |
| `/+1w`       | in a week     |
| `/-1m`       | one month ago |
| `/+1y`       | in one year   |

## Configuration

By default, daily notes are created as `yyyy-mm-dd.md` in the workspace's `journal` folder. The `foam daily` command uses the same location.

To customize your daily note location and format you can create a `.foam/templates/daily-note.md` template. See [[templates]] for more information.

There are also some settings to customize the behavior of daily notes, but they are deprecated and will be removed. Please use the `daily-note.md` template.

To work with daily notes from the terminal, see [[daily|CLI daily command]].

[templates]: templates.md 'Note Templates'
[daily]: ../tools/cli/daily.md 'foam daily'

---

### User Features Embeds (`docs/user/features/embeds.md`)

# Note Embeds

Embeds allow you to include content from other notes directly into your current note. This is powerful for creating dynamic content that updates automatically when the source note changes.

If you want to embed a dynamic list or table of notes instead of the content of one note, see [[foam-queries]].

## Basic Syntax

Use the embed syntax with an exclamation mark before the wikilink:

```markdown
![[note-name]]
```

This will embed the entire content of `note-name` into your current note.

## Embedding Sections

You can embed specific sections of a note by referencing the heading:

```markdown
![[note-name#Section Title]]
```

## Embedding Blocks

Embed a specific paragraph, list item, heading, or blockquote using a block anchor:

```markdown
![[note-name#^blockid]]
```

See [[block-anchors]] for how to add `^id` markers to your notes.

## Embed Types

Foam supports different embedding scopes and styles that can be configured globally or overridden per embed.

### Scope Modifiers

- **`full`** - Include the entire note or section, including the title/heading
- **`content`** - Include everything except the title: the note's first `#` heading, or the section's own heading

Examples:

```markdown
full![[my-note]] # Include title + content
content![[my-note]] # Content only, no title
```

### Style Modifiers

- **`card`** - Display the embedded content in a bordered container
- **`inline`** - Display the content seamlessly as part of the current note

Examples:

```markdown
card![[my-note]] # Bordered container
inline![[my-note]] # Seamless integration
```

#### Custom Card Styling

Customize the appearance of the bordered container in markdown preview by adding CSS:

1. Create `.foam/css/custom-styles.css`
2. Add CSS targeting `.embed-container-note` class:
   ```css
   .embed-container-note {
      border: 1px solid #d1d9e0;
      box-sizing: border-box;
      padding: 4px 16px;
      border-radius: 6px;
   }
   ```
3. Update `.vscode/settings.json`:
   ```json
   {
     "markdown.styles": [".foam/css/custom-styles.css"]
   }
   ```

### Combined Modifiers

You can combine scope and style modifiers:

```markdown
full-card![[my-note]] # Title + content in bordered container
content-inline![[my-note]] # Content only, seamlessly integrated
full-inline![[my-note]] # Title + content, seamlessly integrated
content-card![[my-note]] # Content only in bordered container
```

## Configuration

Set your default embed behavior in VS Code settings:

```json
{
  "foam.preview.embedNoteType": "full-card"
}
```

Available options:

- `full-card` (default)
- `full-inline`
- `content-card`
- `content-inline`

## Image Sizing

Resize images to make your documents more readable:

```markdown
![[image.png|300]]          # 300 pixels wide
![[image.png|50%]]          # Half the container width
```

### Common Use Cases

**Make large screenshots readable:**
```markdown
![[screenshot.png|600]]
```

**Create responsive images:**
```markdown
![[diagram.png|70%]]
```

**Size by width and height:**
```markdown
![[image.png|300x200]]
```

### Alignment

Center, left, or right align images:

```markdown
![[image.png|300|center]]
![[image.png|300|left]]
![[image.png|300|right]]
```

### Alt Text

Add descriptions for accessibility:

```markdown
![[chart.png|400|Monthly sales chart]]
```

### Units

- `300` or `300px` - pixels (default)
- `50%` - percentage of container
- `20em` - relative to font size

### Troubleshooting

- Check image path: `![[path/to/image.png|300]]`
- No spaces around pipes: `|300|` not `| 300 |`
- Images only resize in preview mode, not edit mode
- Use lowercase alignment: `center` not `Center`

[block-anchors]: block-anchors.md 'Block Anchors'
[foam-queries]: foam-queries.md 'Foam Queries'

---

### User Features Foam Queries (`docs/user/features/foam-queries.md`)

# Foam Queries

A Foam Query selects notes by tag, link, property, or other criteria. Queries answer questions like "show my research notes", "list notes linked to this topic", or "count notes in this folder".

Queries are surfaced in two places:

- **Inline in a note** — write a `foam-query` block to render results in the Markdown preview.
- **Saved on disk** — drop a YAML file in `.foam/queries/` to reuse the same query across contexts. VS Code surfaces saved queries as [[smart-folders]] in the side bar.

The query syntax is the same in both. The rest of this page documents that syntax.

For static note embeds, see [[embeds]].

## Saved Queries

Save a query as a YAML file at `.foam/queries/<id>.yaml` to reuse it. The filename (without extension) is the id; rename the file to rename the query.

A saved query inlines the query fields at the root of the YAML, plus two optional wrapper fields:

```yaml
name: Work in Progress           # optional; defaults to a humanized form of the filename
description: Notes I am editing  # optional
filter:
  and:
    - tag: "#wip"
    - not:
        tag: "#archive"
sort: title ASC
limit: 50
```

The minimal valid file is one line: `filter: "#wip"`.

A saved query file is interchangeable with a `foam-query` block — copy the body of one straight into the other.

## Basic Query

Use a `foam-query` code block:

````markdown
```foam-query
filter: "#research"
sort: title ASC
limit: 10
```
````

This renders a list of matching notes in the preview. Query results update as your workspace changes.

If you omit `filter`, Foam searches all notes:

````markdown
```foam-query
format: count
```
````

## Query Options

- `filter`: choose which notes to include
- `select`: choose which fields to display. Default: `title` and `path`
- `sort`: sort results, for example `title ASC` or `backlink-count DESC`. Include the sort field in `select`, otherwise it will not be available after projection.
- `limit`: show only the first `n` matches
- `offset`: skip the first `n` matches
- `format`: render as `list`, `table`, or `count`

When you select more than one field, Foam renders a table by default.

## Filters

### Simple Filters

Use these shortcuts for common cases:

- `"#tag"`: notes with that tag
- `"[[note-id]]"`: notes linked to or from that note (use the same identifier as in wikilinks, e.g. the filename without extension)
- `"/regex/"`: notes whose path matches the regular expression
- `"*"`: all notes

Example:

````markdown
```foam-query
filter: "[[project-alpha]]"
```
````

### Structured Filters

Use YAML when you need more control:

````markdown
```foam-query
filter:
  and:
    - tag: "#research"
    - not:
        path: "^/archive/"
select: [title, tags, backlink-count]
sort: title ASC
```
````

Supported filter keys:

- `tag`: notes that have this tag (e.g. `tag: "#research"`)
- `type`: the kind of file Foam detected — `note` for markdown files, `image` or `attachment` for everything else (e.g. `type: "attachment"`). This is _not_ the `type` you write in a note's frontmatter — to filter on that, use `jexl`
- `path`: notes whose path matches this regex (e.g. `path: "^/projects/"`)
- `title`: notes whose title matches this regex
- `links_to`: notes that link to the given note identifier. Use `"$current"` to refer to the note containing the query
- `links_from`: notes that are linked from the given note identifier. Use `"$current"` to refer to the note containing the query
- `jexl`: a [Jexl](https://github.com/TomFrost/Jexl) expression evaluated against each note, e.g. `"resource.tags|length > 2"`, or `"resource.properties.type == 'daily-note'"` to match notes by their frontmatter `type`. The expression has access to `resource` (with fields `title`, `path`, `type`, `tags`, `properties`, `backlinks`, `outlinks`) and the built-in transforms `length`, `lower`, `upper`. Note: Jexl uses `==` (not `===`) and `|length` (not `.length`). The previous `expression` field is deprecated and no longer evaluated.
- `and`, `or`, `not`: combine filters logically
- _`expression`: REMOVED. A JavaScript expression that used to be evaluated against each note. Replaced by jexl for security reasons; legacy queries match nothing_
- Use `"$current"` in `links_to` or `links_from` to query relative to the note containing the query block:

````markdown
```foam-query
filter:
  links_to: "$current"
```
````

## Displayed Fields

You can select these fields:

- `title` — frontmatter `title` if set, otherwise the first H1 heading, otherwise the filename
- `path` — full workspace-relative path including the filename and extension
- `filename` — the file's name without the extension. Useful when `title` is overridden by frontmatter or an H1 and you still want the on-disk name
- `folder` — the containing folder, e.g. `/projects`
- `extension` — the file extension including the leading dot, e.g. `.md`, or empty string if none
- `type`
- `tags`
- `aliases`
- `sections`
- `blocks`
- `properties` (use `properties.<name>` to pick one)
- `backlink-count`
- `outlink-count`
- `body` — the full note text (frontmatter removed, H1 title kept), rendered as markdown
- `content` — same as `body` but without the H1 title; useful when the title is already shown in another column
- `section[Label]` — the content of the named section (heading removed), rendered as markdown

Example table:

````markdown
```foam-query
filter: "#research"
select: [title, tags, backlink-count]
sort: backlink-count DESC
format: table
```
````

### Including note content in results

To show the full text of each matching note, select `body` or `content`:

````markdown
```foam-query
filter:
  jexl: "resource.properties.status == 'to_ask'"
select: [title, body]
```
````

To show just a named section, use `section[Label]`. Labels may contain spaces:

````markdown
```foam-query
filter:
  jexl: "resource.properties.status == 'to_ask'"
format: table
select:
  - title
  - section[Question]
  - properties.status
```
````

When you write `select:` as a block sequence (each field on its own line, prefixed with `-`), you can use `section[My Label]` directly. If you use the inline form `select: [...]`, YAML treats `[` and `]` as collection delimiters, so quote the value: `select: [title, 'section[My Label]']`.

Section labels are matched **case-sensitively** — `section[Question]` will not match a heading written `## question`.

> `body`, `content`, and `section[...]` aren't supported in VS Code Web — you'll see an inline warning in their place. Everything else works.

### Customising table column headers

By default the table header shows the field expression. For `section[Decision]` and `properties.Status` the wrapper is stripped automatically so you see `Decision` and `Status`. To set an explicit label, use the object form for that entry:

````markdown
```foam-query
filter: "#decisions"
format: table
select:
  - title
  - field: section[Decision]
    label: Chosen Decision
  - field: properties.Status
    label: Question status
```
````

Plain strings and `{ field, label }` objects can be mixed in the same `select`.

### Making cells clickable

By default the `title` column is rendered as a clickable link to the matching note. Every other field is rendered as plain text. You can override that on a per-entry basis with `link`:

````markdown
```foam-query
filter: "#projects"
format: table
select:
  - field: title
    link: false             # render title as plain text
  - field: filename
    link: true              # make filename clickable instead
  - properties.Status
```
````

`link: true` and `link: false` work for any field, and the link target is always the row's note.

## Count Queries

Use `count` when you only need the number of matches:

````markdown
```foam-query
filter:
  path: "^/projects/"
format: count
```
````

## JavaScript Queries

Use `foam-query-js` when YAML is not enough. JavaScript queries only run in a [trusted workspace](https://code.visualstudio.com/docs/editor/workspace-trust). In a trusted workspace, a `foam-query-js` block runs with the same permissions as the rest of VS Code — it can read and write files, make network requests, and run any code your editor can. Treat blocks the same way you'd treat any script you'd download and run: only enable a trusted workspace for notes you author or trust.

````markdown
```foam-query-js
const recentResearch = foam.pages('#research')
  .sortBy('title')
  .limit(5)
  .format('list');

render('Recent research notes:');
render(recentResearch);
```
````

`foam.pages(filter?)` returns a query builder. Omit the filter to include all notes.

`foam.current` is the URI of the note containing the query. Use it to write queries that are relative to the current note:

````markdown
```foam-query-js
// Show all notes that link to this note
render(foam.pages({ links_to: foam.current }).sortBy('title'));
```
````

````markdown
```foam-query-js
// Show all notes that this note links to
render(foam.pages({ links_from: foam.current }).sortBy('title'));
```
````

`foam.current` is `null` if no document is active in the editor.

Available builder methods:

- `where(fn)`: keep only notes where `fn(note)` returns true, e.g. `.where(n => n.tags.includes('draft'))`
- `sortBy(field, direction?)`: sort by field, direction is `'asc'` (default) or `'desc'`
- `limit(n)`: return at most `n` results
- `offset(n)`: skip the first `n` results
- `select(fields)`: project to the given fields. Each entry can be a plain string (e.g. `'title'`) or an object `{ field, label?, link? }` to customise the column header or toggle the per-cell link, e.g. `.select(['title', { field: 'filename', link: true }, { field: 'properties.Status', label: 'State' }])`
- `format(fmt)`: set the output format (`'list'`, `'table'`, or `'count'`)
- `toArray()`: return results as a plain array for use in custom logic

Call `render(...)` to show output in the preview. You can pass a query builder or a plain string.

> Using `.where` together with `body`/`content`/`section[...]` is slow on large workspaces — narrow your results with a regular `foam-query` filter first when you can.

## Trust And Limitations

- `foam-query-js` requires a [trusted workspace](https://code.visualstudio.com/docs/editor/workspace-trust). In a trusted workspace it runs with full editor permissions — no internal sandbox. If you don't trust the source of your notes, keep the workspace untrusted.
- `jexl` filters run in any workspace — Jexl is sandboxed by language design (no host globals, no file system, no network).
- Queries render in Markdown preview, not directly in the editor.
- Query results link back to the matching notes.

[embeds]: embeds.md 'Note Embeds'
[smart-folders]: smart-folders.md 'Smart Folders'

---

### User Features Footnotes (`docs/user/features/footnotes.md`)

# Footnotes

Footnotes let you add references or side notes to your writing without cluttering the main text.

## Writing Footnotes

Use standard Markdown footnote syntax:

```markdown
The study confirmed the hypothesis.[^1] Further work is needed.[^note]

[^1]: Smith et al., 2023, Journal of Examples.
[^note]: See the appendix for the full methodology.
```

Footnote IDs can be numbers or words. The definition can appear anywhere in the file — Foam finds it regardless of position.

## Navigation

Hover over a footnote reference like `[^1]` to see its definition inline.

Press `F12` (or `Ctrl+Click` / `Cmd+Click`) on a reference to jump to its definition in the file.

## Appearance

Footnote references are styled to match wikilinks — the `^id` text is colored. In Preview, footnotes are rendered at the bottom of the note.

## Multiple References

You can reference the same footnote more than once:

```markdown
This point[^caveat] is elaborated elsewhere.[^caveat]

[^caveat]: See the companion article for full details.
```

## Related

- [[wikilinks]] - Linking between notes
- [[block-anchors]] - Linking to specific blocks within a note

[wikilinks]: wikilinks.md "Wikilinks"
[block-anchors]: block-anchors.md "Block Anchors"

---

### User Features Graph View (`docs/user/features/graph-view.md`)

# Graph Visualization

The graph view transforms your notes into a visual network, revealing connections between ideas. To open it, run the `Foam: Show Graph` command.

Files and tags appear as nodes; links between files and file-to-tag relationships are the edges. A node grows in size with the number of connections it has.

### The `Show Graph` command

1. **Press `Ctrl+Shift+P` / `Cmd+Shift+P`**
2. **Type "Foam: Show Graph"**
3. **Press Enter**

You can set up a custom keyboard shortcut:

1. **Go to File > Preferences > Keyboard Shortcuts**
2. **Search for "Foam: Show Graph"**
3. **Assign your preferred shortcut**

## Graph Navigation

With the Foam graph visualization you can:

- highlight a node by hovering on it, to quickly see how it's connected to the rest of your notes
- select one or more (by keeping `shift` pressed while selecting) nodes by clicking on them, to better understand the structure of your notes
- navigate to a note by clicking on it's node while pressing `ctrl` or `cmd`
- automatically center the graph on the currently edited note, to immediately see its connections

### Preview Mode

By default, clicking a node opens the source file in the editor. To open the markdown preview instead, enable the `foam.graph.navigateToPreview` setting:

```json
"foam.graph.navigateToPreview": true
```

This gives you a two-panel layout — graph on one side, rendered preview on the other — without a source editor in between. Non-markdown files (attachments, images, etc.) always open in the editor regardless of this setting.

## Groups

The **Groups** panel (top-right of the graph) controls which nodes are visible and how they are colored. It has three parts:

**Color by** — sets the default coloring strategy for nodes:

- `None` — each node type gets its own color
- `Type` — colors by the note's `type` frontmatter property
- `Directory` — colors by the directory the file lives in

**Built-in types** — checkboxes and color dots for `tag`, `attachment`, `image`, and `placeholder` nodes. Uncheck to hide, click the colored dot to change the color.

**Custom groups** — rules you define to color (and optionally hide) a subset of notes. Each group matches notes by a property and assigns a color. Click `+ Add group` to create one.

A group matches notes by:

- `type` — exact match on the note's type (e.g. `project`)
- `path` — substring match on the file path (e.g. `journal`)
- `tag` — exact match on a tag (e.g. `daily`)
- `title` — substring match on the note title
- Any frontmatter key — exact match on a custom property

Use `/regex/` syntax for pattern matching: e.g. `/^2024/` matches paths starting with `2024`.

Groups layer on top of the default coloring — last matching group wins. Unchecking a group hides notes that only belong to that group.

## Named Views

Define pre-configured graph views in `foam.graph.views`. A view named **`"Default"`** is applied automatically whenever the graph opens — use it to set your preferred starting configuration.

```json
"foam.graph.views": [
  {
    "name": "Default",
    "colorBy": "directory",
    "show": {
      "tag": { "enabled": false },
      "placeholder": { "enabled": false }
    }
  },
  {
    "name": "Journal",
    "colorBy": "directory",
    "show": {
      "tag": { "enabled": false },
      "placeholder": { "enabled": false }
    },
    "groups": [
      {
        "id": "journal",
        "label": "path=journal",
        "color": "#6bcb77",
        "enabled": true,
        "match": { "property": "path", "value": "journal" }
      }
    ]
  }
]
```

Open a named view via a keybinding in `keybindings.json`:

```json
{
  "key": "ctrl+shift+j",
  "command": "foam-vscode.show-graph",
  "args": { "view": "Journal" }
}
```

You can also pass a config inline without a named view:

```json
{
  "key": "ctrl+shift+g",
  "command": "foam-vscode.show-graph",
  "args": {
    "config": {
      "colorBy": "type",
      "show": { "placeholder": { "enabled": false } }
    }
  }
}
```

**View config fields:**

| Field        | Description                                                                            |
| ------------ | -------------------------------------------------------------------------------------- |
| `name`       | Display name shown in the panel title. Use `"Default"` to apply automatically on open. |
| `colorBy`    | `"none"`, `"directory"`, or `"type"`                                                   |
| `groups`     | Array of custom group rules (see Groups section above)                                 |
| `show`       | Per built-in type config: `{ "tag": { "enabled": true, "color": "#ff0000" } }`         |
| `background` | Background color override                                                              |
| `fontSize`   | Font size override                                                                     |
| `fontFamily` | Font family override                                                                   |
| `lineColor`  | Edge color override                                                                    |

All fields are optional. When both `view` and `config` are provided, `config` is merged on top of the named view.

## What's Next?

With graph view mastery, you're ready to explore advanced Foam features:

1. **[[wikilinks]]** - Understand bidirectional connections
2. **[[templates]]** - Use templates effectively to standardize your note creation
3. **[[tags]]** - Organize your notes with tags
4. **[[daily-notes]]** - Set up daily notes to establish capture routines

---

## Legacy: `foam.graph.style`

> **Deprecated.** Configure the graph via `foam.graph.views` instead (see above). Define a `"Default"` view to replace any settings you have in `foam.graph.style`.

`foam.graph.style` still works and is applied as the base layer before any view config:

```json
"foam.graph.style": {
    "background": "#202020",
    "fontSize": 12,
    "fontFamily": "Sans-Serif",
    "lineColor": "#277da1",
    "lineWidth": 0.2,
    "particleWidth": 1.0,
    "highlightedForeground": "#f9c74f",
    "node": {
        "note": "#277da1",
        "placeholder": "#545454",
        "tag": "#f9c74f"
    }
}
```



[wikilinks]: wikilinks.md 'Wikilinks'
[tags]: tags.md 'Tags'
[templates]: templates.md 'Note Templates'
[daily-notes]: daily-notes.md 'Daily Notes'

---

### User Features Link Reference Definitions (`docs/user/features/link-reference-definitions.md`)

# Link Reference Definitions

Link reference definitions make your notes compatible with standard Markdown processors by converting wikilinks to standard Markdown references.

Foam doesn't need references in order to work, but this feature is aimed at supporting other tools you might want to integrate with.

## What Are Link Reference Definitions?

Foam can automatically add reference definitions to the bottom of your notes:

**Your note:**

```markdown
# Machine Learning

Related to [[Data Science]] and [[Statistics]].
```

**With reference definitions:**

```markdown
# Machine Learning

Related to [[Data Science]] and [[Statistics]].

[Data Science]: data-science.md 'Data Science'
[Statistics]: statistics.md 'Statistics'
```

## Enabling Reference Definitions

Configure in your settings:

```json
{
  "foam.edit.linkReferenceDefinitions": "withExtensions"
}
```

**Options:**

- `"off"` - Disabled (default)
- `"withoutExtensions"` - References without extension
- `"withExtensions"` - References with extension

If you are using your notes only within Foam, you can keep definitions `off` (also to reduce clutter), otherwise pick your setting based on what is required by your use case.

## How It Works

1. Scans your note for wikilinks
2. Generates reference definitions when you save
3. Updates definitions when links change
4. Maintains the auto-generated section

## Benefits

- **Standard Markdown compatibility** - Works with any Markdown processor
- **Publishing platforms** - Compatible with GitHub Pages, Jekyll, etc.
- **Future-proofing** - Not locked into Foam-specific format
- **Team collaboration** - Others can read notes without Foam

---

### User Features Note Properties (`docs/user/features/note-properties.md`)

---
type: feature
keywords: hello world, bonjour
tags: [hello, bonjour]
---

# Note Properties

At the top of the file you can have a section where you define your properties. This section is known as the [Front-Matter](https://learn.cloudcannon.com/jekyll/introduction-to-jekyll-front-matter/) of the document and uses [YAML formatting](https://www.codeproject.com/Articles/1214409/Learn-YAML-in-five-minutes).

> Be aware that this YAML section needs to be at the very top of the file to be valid.

For example, for this file, we have:

```markdown
---
type: feature
keywords: hello world, bonjour
---
```

This sets the `type` of this document to `feature` and sets **three** keywords for the document: `hello`, `world`, and `bonjour`. The YAML parser will treat both spaces and commas as the separators for these YAML properties. If you want to use multi-word values for these properties, you will need to combine the words with dashes or underscores (i.e. instead of `hello world`, use `hello_world` or `hello-world`).

> You can set as many custom properties for a document as you like, but there are a few [special properties](#special-properties) defined by Foam.

## Special Properties

Some properties have special meaning for Foam:

| Name    | Description                                                                                                                                                             |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `title` | will assign the name to the note that you will see in the graph, regardless of the filename or the first heading (also see how to [[note-taking-in-foam]])              |
| `type`  | can be used to style notes differently in the graph (also see [[graph-view]]). The default type for a document is `note` unless otherwise specified with this property. |
| `tags`  | can be used to add tags to a note (see [[tags]])                                                                                                                        |
| `alias` | can be used to add aliases to the note. an alias will show up in the link autocompletion                                                                                |

For example:

```markdown
---
title: "Note Title"
type: "daily-note"
tags: daily, funny, planning
alias: alias1, alias2
---
```

## Foam Template Properties

There also exists properties that are even more specific to Foam templates, see [[templates#Metadata]] for more info.

[tags]: tags.md "Tags"
[graph-view]: ../features/graph-view.md "Graph Visualization"
[note-taking-in-foam]: ../getting-started/note-taking-in-foam.md "Note-Taking in Foam"
[templates#Metadata]: templates.md#Metadata "Note Templates"

---

### User Features Paste Images From Clipboard (`docs/user/features/paste-images-from-clipboard.md`)

# Paste Images from Clipboard

By installing the [vscode-paste-image](https://github.com/mushanshitiancai/vscode-paste-image) extension, you can paste an image from the clipboard with `cmd+alt+v`.

Images are automatically copied to the `/attachments` folder and a reference is added in the file where you pasted them.

A prompt will ask you to confirm the name of the image, to disable it set `"pasteImage.showFilePathConfirmInputBox": false,` in the settings.

To change the location where the image is created, change the `pasteImage.path` property, e.g.:

- `${currentFileDir}`: save the image next to the file
- `${currentFileDir}/images`: create an `images` directory next to the file and save the image there

---

### User Features Resource Filters (`docs/user/features/resource-filters.md`)

# Resource Filters

Resource filters can be passed to some Foam commands to limit their scope.

A filter supports the following parameters:

- `tag`: include a resource if it has the given tag (e.g. `{"tag": "#research"}`)
- `type`: include a resource if it is of the given type. Foam assigns `note` to every markdown file, and `image` or `attachment` to other files (e.g. `{"type": "attachment"}`). This is _not_ the `type` you write in a note's frontmatter — to filter on that, use `jexl`
- `path`: include a resource if its path matches the given regex (e.g. `{"path": "/projects/*"}`). **Note that this parameter supports regex and not globs.**
- `jexl`: include a resource if the given [Jexl](https://github.com/TomFrost/Jexl) expression is truthy, where `resource` represents the resource being evaluated (e.g. `{"jexl": "resource.properties.type == 'weekly-note'"}` to match notes by their frontmatter `type`)
- `title`: include a resource if the title matches the given regex (e.g. `{"title": "Team meeting:*"}`)

A filter also supports some logical operators:

- `and`: include a resource if it matches all the sub-parameters (e.g `{"and": [{"tag": "#research"}, {"title": "Paper *"}]}`)
- `or`: include a resource if it matches any of the sub-parameters (e.g `{"or": [{"tag": "#research"}, {"title": "Paper *"}]}`)
- `not`: invert the result of the nested filter (e.g. `{"not": {"type": "attachment"}}`)

Here is an example of a complex filter, to open a resource from a subset of the workspace:

```json
{
  "key": "alt+f",
  "command": "foam-vscode.open-resource",
  "args": {
    "filter": {
      "and": [
        {
          "or": [
            { "jexl": "resource.properties.type == 'daily-note'" },
            { "jexl": "resource.properties.type == 'weekly-note'" },
            { "path": "/projects/*" }
          ]
        },
        { "not": { "tag": "#b" } }
      ]
    }
  }
}
```

---

### User Features Smart Folders (`docs/user/features/smart-folders.md`)

# Smart Folders

Smart Folders are how Foam surfaces your saved queries in the VS Code side bar. Each Smart Folder is a query stored at `.foam/queries/<id>.yaml` — see [[foam-queries]] for the query syntax.

Use them to navigate large workspaces without locking yourself into rigid tag hierarchies. For example: a "Work in Progress" folder showing notes tagged `#wip` but not `#archive`.

## Create a Smart Folder

Open the **Smart Folders** panel in the Explorer and click **Create Smart Folder**, or run the command **Foam: Create Smart Folder**.

You will be asked for:

1. A name (e.g. "Work in Progress")
2. Tags to include (multi-select — press Esc to skip and edit the YAML manually)

Foam creates a YAML file at `.foam/queries/<name>.yaml` and opens it for editing.

## Edit a Smart Folder

Click the pencil icon next to a Smart Folder in the panel, or open the YAML file directly. Changes are picked up automatically.

For the full syntax — structured filters, sorting, links, Jexl expressions — see [[foam-queries]].

## Delete a Smart Folder

Click the trash icon next to a Smart Folder in the panel and confirm. The YAML file is removed.

## View options

In the panel title bar:

- **Group By Folder / Flat list** — group matching notes by their workspace path or show as a flat list
- **Refresh** — re-run all queries on demand

[foam-queries]: foam-queries.md 'Foam Queries'

---

### User Features Spell Checking (`docs/user/features/spell-checking.md`)

# Spell Checking

There are many spell checking extensions for VS Code.

The most popular spell checker for VS Code is [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker).

Another one of our favorites is [LTeX](https://marketplace.visualstudio.com/items?itemName=valentjn.vscode-ltex&ssr=false#overview), which is a bit heavier but offers some extra functionality.

Another popular one is [Spellright](https://marketplace.visualstudio.com/items?itemName=ban.spellright), but be mindful that there have been reports of incompatibility with the `vscode-markdown` extension (see https://github.com/foambubble/foam/issues/1068).

---

### User Features Tags (`docs/user/features/tags.md`)

# Tags

Tags provide flexible categorization and organization for your notes beyond wikilinks and folders.

## Creating Tags

### Inline Tags

Add tags directly in note content:

```markdown
# Machine Learning Fundamentals

This covers basic algorithms and applications.

#machine-learning #data-science #algorithms #beginner
```

### Front Matter Tags

Add tags in YAML front matter:

```markdown
---
tags: [machine-learning, data-science, algorithms, beginner]
---
```

### Hierarchical Tags

Create tag hierarchies using forward slashes:

```markdown
#programming/languages/python
#programming/frameworks/react
#work/projects/website-redesign
#personal/health/exercise
```

## Autocompletion

Typing `#` shows existing tags. In front matter, use `Ctrl+Space` for tag suggestions.

## Tag Explorer

Use the Tag Explorer panel in VS Code's sidebar to:

- Browse hierarchical tag structure
- Filter by tag names
- Click tags to see all associated notes
- View tag usage counts
- Search for tags (click the search icon or use "Foam: Search Tag" command)

Tags also appear in the [[graph-view]] with customizable colors.

## Tag Search

Search for all occurrences of a tag across your workspace:

1. Use the command palette: "Foam: Search Tag"
2. Or click the search icon next to a tag in the Tag Explorer panel

Results appear in VS Code's search panel where you can navigate between matches.

> Known limitation: this command leverages VS Code's search capability, so it's constrained by its use of regular expressions. The search is best-effort and some false search results might show up.

## Custom Tag Styling

Customize tag appearance in markdown preview by adding CSS:

1. Create `.foam/css/custom-tag-style.css`
2. Add CSS targeting `.foam-tag` class:
   ```css
   .foam-tag {
     color: #ffffff;
     background-color: #000000;
   }
   ```
3. Update `.vscode/settings.json`:
   ```json
   {
     "markdown.styles": [".foam/css/custom-tag-style.css"]
   }
   ```

## Tags vs Backlinks

Some users prefer backlinks (e.g. linking to a `book` note) instead of #book tags for categorization. Both approaches work — choose what fits your workflow.

To manage tags from the terminal, see [[tag|CLI tag command]].

[graph-view]: graph-view.md 'Graph Visualization'
[tag]: ../tools/cli/tag.md 'foam tag'

---

### User Features Templates (`docs/user/features/templates.md`)

# Note Templates

Foam supports note templates which let you customize the starting content of your notes instead of always starting from an empty note.

Foam supports two types of templates:

- **Markdown templates** (`.md` files) - Simple templates with predefined content and variables
- **JavaScript templates** (`.js` files) - Smart templates that can adapt based on context and make intelligent decisions

Both types of templates are located in the special `.foam/templates` directory of your workspace.

## Quickstart

### Creating templates

**For simple templates:**

- Run the `Foam: Create New Template` command from the command palette
- OR manually create a regular `.md` file in the `.foam/templates` directory

**For smart templates:**

- Create a `.js` file in the `.foam/templates` directory (see [JavaScript Templates](#javascript-templates) section below)



### Using templates

To create a note from a template:

- Run the `Foam: Create New Note From Template` command and follow the instructions. Don't worry if you've not created a template yet! You'll be prompted to create a new simple template if none exist.
- OR run the `Foam: Create New Note` command, which uses the special default template (`.foam/templates/new-note.md` or `.foam/templates/new-note.js`, if it exists)



## Multi-root workspaces

If your VS Code workspace has several folders, see [[multi-root-workspaces]] for where Foam looks for templates and how to create notes in a specific folder.

## Special templates

### Default template

The default template is used by the `Foam: Create New Note` command. Foam will look for these templates in order:

1. `.foam/templates/new-note.js` (JavaScript template)
2. `.foam/templates/new-note.md` (Markdown template)

Customize this template to contain content that you want included every time you create a note.

### Default daily note template

The daily note template is used when creating daily notes (e.g. by using `Foam: Open Daily Note`). Foam will look for these templates in order:

1. `.foam/templates/daily-note.js` (JavaScript template)
2. `.foam/templates/daily-note.md` (Markdown template)

For a simple markdown template, it is _recommended_ to define the YAML Front-Matter similar to the following:

```markdown
---
type: daily-note
---
```

## JavaScript Templates

JavaScript templates are a powerful way to create smart, context-aware note templates that can adapt based on the situation. Unlike static Markdown templates, JavaScript templates can make intelligent decisions about what content to include.

**Use JavaScript templates when you want to:**

- Create different note structures based on the day of the week, time, or date
- Adapt templates based on where the note is being created from
- Automatically find and link related notes in your workspace
- Generate content based on existing notes or workspace structure
- Implement complex logic that static templates cannot handle

### Basic JavaScript template structure

A JavaScript template is a `.js` file that exports a function returning note content, and optionally location:

```javascript
// .foam/templates/daily-note.js
async function createNote({ trigger, foam, resolver, foamDate }) {
  const today = dayjs();
  // or you could use foamDate for day specific notes, see FOAM_DATE_* variables
  // const day = dayjs(foamDate)
  const formattedDay = today.format('YYYY-MM-DD');

  // if you need a variable you can use the resolver
  // const title = await resolver.resolveFromName('FOAM_TITLE');

  console.log('Creating note for today: ' + formattedDay, JSON.stringify(trigger));

  let content = `# Daily Note - ${formattedDay}

## Today's focus
- 

## Notes
- 
`;

  switch (today.day()) {
    case 1: // Monday
      content = `# Week Planning - ${formattedDay}

## This week's goals
- [ ] Goal 1
- [ ] Goal 2

## Focus areas
- 
`;
      break;
    case 5: // Friday
      content = `# Week Review - ${formattedDay}

## What went well
- 

## What could be improved
- 

## Next week's priorities
- 
`;
      break;
  }

  return {
    content,
    filepath: `/weekly-planning/${formattedDay}.md`,
  };
}
```

### Examples

**Smart meeting notes:**

```javascript
async function createNote({ trigger, foam, resolver }) {
  const title = (await resolver.resolveFromName('FOAM_TITLE')) || 'Meeting';
  const today = dayjs();
  // Detect meeting type from title
  const isStandup = title.toLowerCase().includes('standup');
  const isReview = title.toLowerCase().includes('review');

  let template = `# ${title} - ${today.format('YYYY-MM-DD')}

`;

  if (isStandup) {
    template += `## What I did yesterday
- 

## What I'm doing today
- 

## Blockers
- 
`;
  } else if (isReview) {
    template += `## What went well
- 

## What could be improved
- 

## Action items
- [ ] 
`;
  } else {
    template += `## Agenda
- 

## Notes
- 

## Action items
- [ ] 
`;
  }

  return {
    content: template,
    filepath: `/meetings/${title}.md`,
  };
}
```

### Template result format

JavaScript templates must return an object with:

- `content` (required): The note content as a string. Foam variables in it (e.g. `${FOAM_TITLE}`) are resolved like in a Markdown template
- `filepath` (required): Custom file path for the note
  - NOTE: the path must be within the workspace.
    - A relative path will be resolved based on the `onRelativePath` command configuration.
    - An absolute path will be taken as is, if it falls within the workspace. Otherwise it will be considered to be from the workspace root

```javascript
return {
  content: '# My Note\n\nContent here...',
  filepath: 'custom-folder/my-note.md',
};
```

### Tab stops

[VS Code tab stops](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax) work in `content`, but `${...}` is also JavaScript template literal syntax. Escape the `$` so the tab stop reaches the note:

```javascript
const content = `# ${title}

## Mood
\${1:great}

## To-dos
- [ ] \${2}
`;
```

### Security and limitations

JavaScript templates execute real JavaScript. Foam guards where and when
they run, but the in-process sandbox is **not** a security boundary — a
malicious template can escape it. Trust controls are the real protection:

- ✅ Only run in **trusted** VS Code workspaces
- ✅ When using the `foam` CLI, only run with the `--trust` flag
- ❌ **Never run under the MCP server.** `foam mcp` and the
  `create_resource` tool refuse `.js` templates with an
  `untrusted_workspace` error
- ⏱ 10-second execution timeout

> ⚠️ **Treat a `new-note.js` like a script you'd execute by hand.
> ** Only use JS templates from workspaces whose contributors you trust.

If you don't need the power of arbitrary JavaScript, prefer a Markdown
template — those run everywhere (CLI, MCP, web extension) and have no
trust requirement.

## Markdown templates

Markdown templates are a simple way to create notes

**Use Markdown templates when you want to:**

- Create simple, consistent note structures
- Use basic variables and placeholders
- Keep templates easy to read and modify

### Variables

Markdown templates can use all the variables available in [VS Code Snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables).

In addition, you can also use variables provided by Foam:

| Name                 | Description                                                                                                                                                                                                                                                                                |
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `FOAM_SELECTED_TEXT` | Foam will fill it with selected text when creating a new note, if any text is selected. Selected text will be replaced with a wikilink to the new                                                                                                                                          |
| `FOAM_TITLE`         | The title of the note. If used, Foam will prompt you to enter a title for the note.                                                                                                                                                                                                        |
| `FOAM_TITLE_SAFE`    | The title of the note in a file system safe format. If used, Foam will prompt you to enter a title for the note unless `FOAM_TITLE` has already caused the prompt.                                                                                                                         |
| `FOAM_SLUG`          | The sluggified title of the note (using the default github slug method). If used, Foam will prompt you to enter a title for the note unless `FOAM_TITLE` has already caused the prompt.                                                                                                    |
| `FOAM_CURRENT_DIR`   | The current editor's directory path. Resolves to the directory of the currently active file, or falls back to workspace root if no editor is active. Useful for creating notes in the current directory context.                                                                           |
| `FOAM_PREVIOUS_DAILY_NOTE` | The most recent daily note that exists before the one being created, skipping any gap. Daily note templates only. See [[daily-notes]].                                                                                                                                              |
| `FOAM_DATE_FORMAT`   | The Foam date formatted using a [dayjs format string](https://day.js.org/docs/en/display/format). Defaults to ISO 8601 with local timezone offset (e.g. `2026-03-12T22:06:55+01:00`). Use as `$FOAM_DATE_FORMAT` for the default, or `${FOAM_DATE_FORMAT:YYYY-MM-DD}` for a custom format. |
| `FOAM_DATE_*`        | `FOAM_DATE_YEAR`, `FOAM_DATE_MONTH`, `FOAM_DATE_WEEK`, `FOAM_DATE_DAY_ISO` etc. Foam-specific versions of [VS Code's datetime snippet variables](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables). Prefer these versions over VS Code's.                          |

### Tab stops

Use [VS Code tab stops](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_snippet-syntax) to jump the cursor through the new note with `Tab`:

```markdown
# $FOAM_TITLE

## Mood
${1:great}

## To-dos
- [ ] ${2}
```

### `FOAM_DATE_FORMAT` variable

`FOAM_DATE_FORMAT` lets you format the Foam date using a [dayjs format string](https://day.js.org/docs/en/display/format):

- `$FOAM_DATE_FORMAT` — ISO 8601 local datetime with timezone offset, e.g. `2026-03-12T22:06:55+01:00`
- `${FOAM_DATE_FORMAT:YYYY-MM-DD}` — date only, e.g. `2026-03-12`
- `${FOAM_DATE_FORMAT:HH:mm}` — time only, e.g. `22:06`

The format string (the part after `:`) uses [dayjs tokens](https://day.js.org/docs/en/display/format). Common tokens: `YYYY` (4-digit year), `MM` (month), `DD` (day), `HH` (hour), `mm` (minute), `ss` (second), `Z` (timezone offset).

Like all `FOAM_DATE_*` variables, this uses the Foam date rather than the current time, so it works correctly with relative daily notes (e.g. `/tomorrow`).

### `FOAM_DATE_*` variables

Foam defines its own set of datetime variables that have a similar behaviour as [VS Code's datetime snippet variables](https://code.visualstudio.com/docs/editor/userdefinedsnippets#_variables).

Supported variables include:

- `FOAM_DATE_YEAR`: 4-digit year (e.g. 2025)
- `FOAM_DATE_MONTH`: 2-digit month (e.g. 09)
- `FOAM_DATE_WEEK`: ISO 8601 week number (e.g. 37)
- `FOAM_DATE_WEEK_YEAR`: the year of the ISO 8601 week number. The year that contains the Thursday of the current week, may vary from calendar year near Jan 1. Often used with `FOAM_DATE_WEEK`.
- `FOAM_DATE_DAY_ISO`: ISO 8601 weekday number (1-7, where Monday=1, Sunday=7)
- `FOAM_DATE_DATE`: 2-digit day of month (e.g. 15)
- `FOAM_DATE_DAY_NAME`: Full weekday name (e.g. Monday)
- `FOAM_DATE_DAY_NAME_SHORT`: Short weekday name (e.g. Mon)
- `FOAM_DATE_HOUR`, `FOAM_DATE_MINUTE`, `FOAM_DATE_SECOND`, `FOAM_DATE_SECONDS_UNIX`, etc.

For example, `FOAM_DATE_YEAR` has the same behaviour as VS Code's `CURRENT_YEAR`, `FOAM_DATE_SECONDS_UNIX` has the same behaviour as `CURRENT_SECONDS_UNIX`, etc. `FOAM_DATE_DAY_ISO` returns the ISO weekday number (Monday=1, Sunday=7), which is useful for ISO week date formats like `2025-W37-5`.

By default, prefer using the `FOAM_DATE_` versions. The datetime used to compute the values will be the same for both `FOAM_DATE_` and VS Code's variables, with the exception of the creation notes using the daily note template.

For more nitty-gritty details about the supported date formats, [see here](https://github.com/foambubble/foam/blob/main/packages/foam-core/src/templates/variable-resolver.ts).

#### Relative daily notes

When referring to daily notes, you can use the relative snippets (`/+1d`, `/tomorrow`, etc.). In these cases, the new notes will be created with the daily note template, but the datetime used should be the relative datetime, not the current datetime.
By using the `FOAM_DATE_` versions of the variables, the correct relative date will populate the variables, instead of the current datetime.

For example, given this daily note template (`.foam/templates/daily-note.md`):

```markdown
# $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE

## Here's what I'm going to do today

- Thing 1
- Thing 2
```

When the `/tomorrow` snippet is used, `FOAM_DATE_` variables will be populated with tomorrow's date, as expected.
If instead you were to use the VS Code versions of these variables, they would be populated with today's date, not tomorrow's, causing unexpected behaviour.

When creating notes in any other scenario, the `FOAM_DATE_` values are computed using the same datetime as the VS Code ones, so the `FOAM_DATE_` versions can be used in all scenarios by default.

### Metadata

**Markdown templates** can also contain metadata about the templates themselves. The metadata is defined in YAML "Frontmatter" blocks within the templates.

| Name          | Description                                                                                                                      |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `filepath`    | The filepath to use when creating the new note. If the filepath is a relative filepath, it is relative to the current workspace. |
| `name`        | A human readable name to show in the template picker.                                                                            |
| `description` | A human readable description to show in the template picker.                                                                     |

Foam-specific variables (e.g. `$FOAM_TITLE`) can be used within template metadata. However, VS Code snippet variables are ([currently](https://github.com/foambubble/foam/pull/655)) not supported.

#### `filepath` attribute

> In a [restricted workspace](https://code.visualstudio.com/docs/editor/workspace-trust), notes must be created inside the workspace: a `filepath` that points outside it is refused. Trust the workspace to allow it.

It is possible to vary the `filepath` value based on the current date using the `FOAM_DATE_*` variables. This is especially useful for the [[daily-notes]] template if you wish to organize by years, months, etc. Below is an example of a daily-note template metadata section that will create new daily notes under the `journal/YEAR/MONTH-MONTH_NAME/` filepath. For example, when a note is created on November 15, 2022, a new file will be created at `C:\Users\foam_user\foam_notes\journal\2022\11-Nov\2022-11-15-daily-note.md`. This method also respects the creation of daily notes relative to the current date (i.e. `/+1d`).

```markdown
---
type: daily-note
foam_template:
  description: Daily Note
  filepath: '/journal/$FOAM_DATE_YEAR/$FOAM_DATE_MONTH-$FOAM_DATE_MONTH_NAME_SHORT/$FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE-daily-note.md'
---

# $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE Daily Notes
```

##### Creating notes in the current directory

To create notes in the same directory as your currently active file, use the `FOAM_CURRENT_DIR` variable in your template's `filepath`:

```markdown
---
foam_template:
  name: Current Directory Note
  filepath: '$FOAM_CURRENT_DIR/$FOAM_SLUG.md'
---

# $FOAM_TITLE

$FOAM_SELECTED_TEXT
```

**Best practices for filepath patterns:**

- **Explicit current directory:** `$FOAM_CURRENT_DIR/$FOAM_SLUG.md` - Creates notes in the current editor's directory
- **Workspace root:** `/$FOAM_SLUG.md` - Always creates notes in workspace root
- **Subdirectories:** `$FOAM_CURRENT_DIR/meetings/$FOAM_SLUG.md` - Creates notes in subdirectories relative to current location

The `FOAM_CURRENT_DIR` approach is recommended over relative paths (like `./file.md`) because it makes the template's behavior explicit and doesn't depend on configuration settings.

#### `name` and `description` attributes

These attributes provide a human readable name and description to be shown in the template picker (e.g. When a user uses the `Foam: Create New Note From Template` command):



#### Adding template metadata to an existing YAML Frontmatter block

If your template already has a YAML Frontmatter block, you can add the Foam template metadata to it.

Foam only supports adding the template metadata to _YAML_ Frontmatter blocks. If the existing Frontmatter block uses some other format (e.g. JSON), you will have to add the template metadata to its own YAML Frontmatter block.

Further, the template metadata must be provided as a [YAML block mapping](https://yaml.org/spec/1.2/spec.html#id2798057), with the attributes placed on the lines immediately following the `foam_template` line:

```yaml
---
existing_frontmatter: "Existing Frontmatter block"
foam_template: # this is a YAML "Block" mapping ("Flow" mappings aren't supported)
  name: My Note Template # Attributes must be on the lines immediately following `foam_template`
  description: This is my note template
  filepath: `journal/$FOAM_TITLE.md`
---
This is the rest of the template
```

#### Adding template metadata to its own YAML Frontmatter block

You can add the template metadata to its own YAML Frontmatter block at the start of the template:

```yaml
---
foam_template:
  name: My Note Template
  description: This is my note template
  filepath: 'journal/$FOAM_TITLE.md'
---
This is the rest of the template
```

If the note already has a Frontmatter block, a Foam-specific Frontmatter block can be added to the start of the template. The Foam-specific Frontmatter block must always be placed at the very beginning of the file, and only whitespace can separate the two Frontmatter blocks.

```yaml
---
foam_template:
  name: My Note Template
  description: This is my note template
  filepath: 'journal/$FOAM_TITLE.md'
---

---
existing_frontmatter: 'Existing Frontmatter block'
---
This is the rest of the template
```

[daily-notes]: daily-notes.md 'Daily Notes'
[multi-root-workspaces]: ../recipes/multi-root-workspaces.md 'Multi-root workspaces'

---

### User Features Wikilinks (`docs/user/features/wikilinks.md`)

# Wikilinks

Wikilinks are internal links that connect files in your knowledge base using `[[double bracket]]` syntax.

## Creating Wikilinks

1. **Type `[[`** and start typing a note name
2. **Select from autocomplete** and press `Tab`
3. **Navigate** with `Ctrl+Click` (`Cmd+Click` on Mac) or `F12`
4. **Create new notes** by clicking on non-existent wikilinks

Example: [[graph-view]]

## Placeholders

Wikilinks to non-existent files create placeholder links, styled differently to show they need files created. They're useful for planning your knowledge structure.

View placeholders in the graph with `Foam: Show Graph` command or in the `Placeholders` panel.

## Section Links

Link to specific sections using `[[note-name#Section Title]]` syntax. Foam provides autocomplete for section titles.

Examples:

- External file: `[link text](other-file.md#section-name)`
- Same document: `[link text](#section-name)`

## Block Links

Link to a specific paragraph, list item, heading, or blockquote using `[[note-name#^blockid]]` syntax. Add a `^your-id` anchor at the end of any block element, then reference it from other notes.

See [[block-anchors]] for full details.

## Directory Links

Linking to a folder name navigates to that folder's index file — either `index.md` or `README.md`. This works for both wikilinks and regular markdown links:

- `[[projects]]` → opens `projects/index.md` (or `projects/README.md`)
- `[Projects](projects)` → same
- `[Projects](projects/)` → trailing slash is ignored

If a file named `projects.md` exists alongside the `projects/` folder, it takes priority.

To disable this behavior, set `foam.links.directory.mode` to `disabled` in your VS Code settings.

## Link Syncing on Rename

When you rename or move a note or folder, Foam automatically updates all wikilinks pointing to it. This is enabled by default and can be turned off via the `foam.links.sync.enable` setting.

For standard markdown links (e.g. `[text](path/to/note.md)`), VS Code has a built-in feature that handles this. Enable it in VS Code settings: set `markdown.updateLinksOnFileMove.enabled` to `always` or `prompt`.

## Path vs Identifier Links

Wikilinks come in two forms:

- **Identifier links** — `[[filename]]`, `[[folder/filename]]` — identify a resource by name, resolved relative to the whole workspace
- **Path links** — `[[./file]]`, `[[../other/file]]`, `[[/from/root]]` — identify a resource by its file path

The rule: if the link starts with `/` or `.`, it's a path reference; otherwise it's an identifier.

For identifier links, you can use any suffix that uniquely identifies the file. Given `projects/house/todo.md` and `work/todo.md`, the identifiers `[[todo]]` (ambiguous), `[[house/todo]]` (unique), and `[[projects/house/todo]]` (unique) are all valid — Foam picks the shortest unambiguous form.

## Ambiguous Links

When the same filename exists in multiple locations, `[[todo]]` is ambiguous. Foam resolves it alphabetically (deterministic), and shows a warning diagnostic so you can use a more specific identifier like `[[house/todo]]`.

## Markdown Compatibility

Foam can automatically generate [[link-reference-definitions]] at the bottom of files to make wikilinks compatible with standard Markdown processors.

## Compatibility with Other Apps

| Wikilink                       | Obsidian                        | Foam                            |
| ------------------------------ | ------------------------------- | ------------------------------- |
| `[[notes]]`                    | ✔ unique identifier in repo     | ✔ unique identifier in repo     |
| `[[/work/notes]]`              | ✔ valid path from repo root     | ✔ valid path from repo root     |
| `[[work/notes]]`               | ✔ valid path from repo root     | ✔ valid identifier in repo      |
| `[[project/house/todo]]`       | ✔ valid path from repo root     | ✔ valid unique identifier       |
| `[[/project/house/todo]]`      | ✔ valid path from repo root     | ✔ valid path from repo root     |
| `[[house/todo]]`               | ✔ valid unique identifier       | ✔ valid unique identifier       |
| `[[todo]]` (ambiguous)         | ✘ ambiguous identifier          | ✘ ambiguous identifier          |
| `[[/house/todo]]` (wrong path) | ✘ incorrect path from repo root | ✘ incorrect path from repo root |

## Related

- [[footnotes]] - Adding references and side notes
- [[block-anchors]] - Linking to specific blocks within a note
- [[templates]] - Creating new notes

[link-reference-definitions]: link-reference-definitions.md 'Link Reference Definitions'
[footnotes]: footnotes.md 'Footnotes'
[block-anchors]: block-anchors.md 'Block Anchors'
[graph-view]: graph-view.md "Graph Visualization"
[templates]: templates.md "Note Templates"

---

### User Getting Started First Workspace (`docs/user/getting-started/first-workspace.md`)

# Creating Your First Workspace

A Foam workspace is where all your notes, ideas, and knowledge live. Think of it as your digital garden where thoughts can grow and connect. This guide will help you set up a workspace that's organized, scalable, and tailored to your thinking style.

## Understanding Workspaces

A Foam workspace is simply a folder containing **Markdown files** (`.md`) - your actual notes.

Optionally it can contain:

- **Configuration files** - VS Code settings and Foam preferences
- **Assets** - images, attachments, and other media
- **Templates** - reusable note structures

### Single vs. Multiple Workspaces

**Recommended: Single Workspace**

- Keep all your knowledge in one place
- Better link discovery and graph visualization
- Easier to maintain and backup
- Follows the "unified knowledge base" principle

**Deprecated: Multiple Workspaces** (deprecated - advanced users only)

- Separate professional and personal knowledge
- Isolate sensitive information
- Different workflows for different projects

Multiple workspaces are to be considered deprecated at this point, and might become unsupported in the future.
You can simulate a complex workspace by using file/folder links.

## Method 1: Using the Foam Template (Recommended)

The easiest way to start is with our pre-configured template:

### Step 1: Create from Template

1. **Visit** [github.com/foambubble/foam-template](https://github.com/foambubble/foam-template)
2. **Click "Use this template"** (you'll need a GitHub account)
3. **Name your repository** (e.g., "john-knowledge-base", "my-second-brain")
4. **Choose visibility:**
   - **Private** - for personal notes (recommended)
   - **Public** - if you want to share your knowledge openly

### Step 2: Clone Locally

```bash
git clone https://github.com/yourusername/your-repo-name.git
cd your-repo-name
```

### Step 3: Open in VS Code

1. **Launch VS Code**
2. **File > Open Folder**
3. **Select your cloned repository folder**

## Method 2: Start from Scratch

For a minimal setup:

1. **Create a new folder** on your computer
2. **Open the folder** in VS Code (`File > Open Folder`)

That's all, you can start working with your markdown files and Foam will take care of the rest.

> Already have an Obsidian vault? You can open it directly in VS Code — see [[migrating-from-obsidian]].

## Ideas for your knowledge base

### 1. Customize Your Settings

Review and adjust `.vscode/settings.json` based on your preferences:

- **Daily notes location** - where your daily notes are stored
- **Image handling** - how pasted images are organized
- **Link format** - with or without file extensions

### 2. Set Up Your Inbox

Create `inbox.md` as your default capture location:

```markdown
# Inbox

Quick notes and ideas go here before being organized.

## Today's Captures

-

## To Process

-

## Ideas

-
```

### 3. Create Core Structure Notes

## Workspace Organization Strategies

Establish your main organizational notes.
You can use any methodology, Foam is not opinionated.

The only recommendation is to get started, you can improve later.

The two main methods adopted by users are [PARA](https://fortelabs.com/blog/para/) and [Zettelkasten](https://zettelkasten.de/overview/).

### The PARA Method

Organize around four categories:

- **Projects** - Things with deadlines
- **Areas** - Ongoing responsibilities
- **Resources** - Future reference materials
- **Archive** - Inactive items

### Zettelkasten Approach

Number-based system for atomic ideas:

- **Permanent notes** - `202501251030-idea-title.md`
- **Literature notes** - `book-author-year.md`
- **Index notes** - `index-topic.md`

### 4. Configure Daily Notes

Daily notes are perfect for:

- Daily planning and reflection
- Meeting notes
- Journal entries
- Quick captures

Test your daily notes setup:

1. **Press `Ctrl+Shift+P` / `Cmd+Shift+P`**
2. **Type "Foam: Open Daily Note"**
3. **Verify the note is created in the right location**

Alternatively you can press `Alt+D` to open today's daily note, or `Alt+H` to open another day's daily note.
Use the `.foam/templates/daily-note.md` to customize your daily note.

## Best Practices for New Workspaces

### 1. Start Small

- Begin with just a few notes
- Don't over-organize initially
- Let structure emerge naturally

### 2. Use Templates

- Create templates for common note types
- Maintain consistency across similar notes
- Save time on repetitive formatting

### 3. Link Early and Often

- Use `[[wikilinks]]` liberally
- Don't worry about creating "perfect" links
- Foam handles broken links gracefully

### 4. Regular Reviews

- Weekly workspace cleanup
- Archive completed projects
- Identify missing connections

## Syncing and Backup

Foam works on simple files, you can add whatever backup method you prefer on top of it.

### Git

Your workspace is a Git repository:

```bash
git add .
git commit -m "Add new notes and ideas"
git push origin main
```

You can also use other VS Code extensions to manage the git synching if that's helpful.

### Alternative Sync Methods

- **Cloud storage** - Dropbox, OneDrive, Google Drive
- **Local backup** - Time Machine, File History
- **Manual export** - Regular ZIP backups

## What's Next?

With your workspace set up, you're ready to:

1. **[Learn note-taking fundamentals](note-taking-in-foam.md)** - Master Markdown and writing effective notes
2. **[Explore navigation](navigation.md)** - Connect your thoughts with wikilinks
3. **[Discover the graph view](../features/graph-view.md)** - Visualize your knowledge network
4. **[Set up templates](../features/templates.md)** - Standardize your note creation process

## Getting Help

If you encounter setup issues:

- Check the [Installation Guide](installation.md) for prerequisites
- Visit the [[frequently-asked-questions]] for common workspace problems
- Join the [Foam Community Discord](https://discord.com/invite/HV2tn2FpEk)

[frequently-asked-questions]: ../frequently-asked-questions.md 'Frequently Asked Questions'
[migrating-from-obsidian]: ../recipes/migrating-from-obsidian.md "Coming from Obsidian"

---

### User Getting Started Get Started With Vscode (`docs/user/getting-started/get-started-with-vscode.md`)

# Using Foam with VS Code Features

Foam builds on Visual Studio Code's powerful editing capabilities, integrating seamlessly with VS Code's native features to create a comprehensive knowledge management experience. This guide explores how to leverage VS Code's built-in functionality alongside Foam.

### Keyboard shortcuts

VS Code supports various **keyboard shortcuts**, the most important for us are:

| Shortcut      | Action                        |
| ------------- | ----------------------------- |
| `cmd+N`       | create a new file             |
| `cmd+S`       | save the current file         |
| `cmd+O`       | open a file                   |
| `cmd+P`       | use quickpick to open a file  |
| `alt+D`       | open the daily note for today |
| `alt+H`       | open the daily note for a day |
| `cmd+shift+P` | invoke a command (see below)  |

For more information, see the [VS Code keyboard cheat sheets](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-reference), where you can also see how to customize your keybindings.

### Commands

Commands make VS Code extremely powerful.

To invoke a command, press `cmd+shift+P` and select the command you want to execute.
For example, to see the Foam graph:

- press `cmd+shift+P` to open the command bar
- start typing `show graph`
- select the `Foam: Show Graph` command

And watch the magic unfold.

To see all foam commands, type "foam" in the command bar.
For more information on commands, see [commands on the VS Code site](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).

If you want to learn more about VS Code, check out their [website](https://code.visualstudio.com/docs#first-steps).

### Panels

Foam integrates with VS Code panels to provide insights into individual notes and the whole knowledge base.

- **`Foam: links`**: Shows all notes that link to and from the currently active note, helping you understand connections and navigate your knowledge graph
- **`Foam: Orphaned Notes`**: Displays notes that have no incoming or outgoing links, helping you identify isolated content that might need better integration
- **`Tag Explorer`**: Shows all tags used across your workspace in a hierarchical view, see [[tags]] for more information on tags
- **`Foam: Graph`**: Visual representation of your note connections (also available as a separate graph view)

### Styling and Themes

VS Code is very configurable when it comes to themes and style. Find your ideal set up by running the command `Color Theme`.
For more information see the [VS Code documentation](https://code.visualstudio.com/docs/configure/themes).

### Multi-Cursor Editing

Edit multiple locations simultaneously for efficient note management:

**Basic Multi-Cursor:**

- `Alt+Click` / `Option+Click` - Add cursor at click location
- `Ctrl+Alt+Down` / `Cmd+Option+Down` - Add cursor below
- `Ctrl+Alt+Up` / `Cmd+Option+Up` - Add cursor above
- `Ctrl+D` / `Cmd+D` - Select next occurrence of word
- `Ctrl+Shift+L` / `Cmd+Shift+L` - Select all occurrences

**Bulk wikilink creation:**

1. **Select a word** (e.g., "Python")
2. **Press `Ctrl+Shift+L`** to select all occurrences
3. **Type `[[]]`** to wrap all instances
4. **Arrow key** to position cursor inside brackets

### Find and Replace

Powerful search and replace for note maintenance:

**Basic Find/Replace:**

- `Ctrl+F` / `Cmd+F` - Find in current file
- `Ctrl+H` / `Cmd+H` - Replace in current file
- `Ctrl+Shift+F` / `Cmd+Shift+F` - Find across workspace
- `Ctrl+Shift+H` / `Cmd+Shift+H` - Replace across workspace

### Text Folding

Organize long notes with collapsible sections:

**Folding Controls:**

- **Click fold icons** in the gutter next to headings
- `Ctrl+Shift+[` / `Cmd+Option+[` - Fold current section
- `Ctrl+Shift+]` / `Cmd+Option+]` - Unfold current section
- `Ctrl+K Ctrl+0` / `Cmd+K Cmd+0` - Fold all
- `Ctrl+K Ctrl+J` / `Cmd+K Cmd+J` - Unfold all

## File Management

### Explorer Integration

Leverage VS Code's file explorer for note organization:

**File Operations:**

- **Drag and drop** files to reorganize
- **Right-click context menus** for quick actions
- **New file/folder** creation with shortcuts
- **Bulk selection** with Ctrl+Click / Cmd+Click

**Quick File Actions:**

- `F2` - Rename file (Foam updates links automatically)
- `Delete` - Move to trash
- `Ctrl+C` / `Cmd+C` then `Ctrl+V` / `Cmd+V` - Copy/paste files
- **Right-click → Reveal in Explorer/Finder** - Open in file system

### Quick Open

Rapid file navigation for large knowledge bases:

**Quick Open Commands:**

- `Ctrl+P` / `Cmd+P` - Go to file
- `Ctrl+Shift+O` / `Cmd+Shift+O` - Go to symbol (headings in Markdown)
- `Ctrl+T` / `Cmd+T` - Go to symbol in workspace
- `Ctrl+G` / `Cmd+G` - Go to line number

**Search Patterns:**

```
# Go to File (Ctrl+P)
machine       # Finds "machine-learning.md"
proj alpha    # Finds "project-alpha.md"
daily/2025    # Finds files in daily/2025 folder

# Go to Symbol (Ctrl+Shift+O)
@introduction # Jump to "Introduction" heading
@#setup       # Jump to "Setup" heading
:50           # Go to line 50
```

## Search and Discovery

### Global Search

Find content across your entire knowledge base:

**Search Interface (`Ctrl+Shift+F` / `Cmd+Shift+F`):**

- **Search box** - Enter your query
- **Replace box** - Toggle with replace arrow
- **Include/Exclude patterns** - Filter by file types or folders
- **Match case** - Case-sensitive search
- **Match whole word** - Exact word matching
- **Use regular expression** - Advanced pattern matching

### Timeline View

Track changes to your notes over time:

**Accessing Timeline:**

1. **Open Explorer panel**
2. **Expand "Timeline" section** at bottom
3. **Select a file** to see its change history
4. **Click timeline entries** to see diff views

**Timeline Features:**

- **Git commits** show when notes were changed
- **File saves** track editing sessions
- **Diff views** highlight what changed
- **Restore points** for recovering previous versions

### Outline View

Navigate long notes with hierarchical structure:

**Outline Panel:**

1. **Enable in Explorer** (expand "Outline" section)
2. **Shows heading hierarchy** for current note
3. **Click headings** to jump to sections
4. **Collapse/expand** sections in outline

## Version Control Integration

### Git Integration

Track changes to your knowledge base:

**Source Control Panel:**

- **View changes** - See modified files
- **Stage changes** - Click `+` to stage files
- **Commit changes** - Enter message and commit
- **Sync changes** - Push/pull from remote

**Git Workflow for Notes:**

1. **Write and edit** your notes
2. **Review changes** in Source Control panel
3. **Stage relevant files** for commit
4. **Write meaningful commit message**
5. **Commit and push** to backup/share

**Useful Git Features:**

- **Diff view** - See exactly what changed
- **File history** - Track note evolution over time
- **Branch management** - Experiment with different organization approaches
- **Merge conflicts** - Resolve when collaborating

## Markdown Features

### Preview Integration

View formatted notes alongside editing:

**Preview Commands:**

- `Ctrl+Shift+V` / `Cmd+Shift+V` - Open preview
- `Ctrl+K V` / `Cmd+K V` - Open preview to side
- **Preview lock** - Pin preview to specific file

**Diagrams (with Mermaid extension):**

````markdown
```mermaid
graph TD
    A[Foam Workspace] --> B[Notes]
    A --> C[Templates]
    A --> D[Assets]
    B --> E[Wikilinks]
    B --> F[Tags]
    E --> G[Graph View]
```
````

## Extension Ecosystem

Extend Foam's capabilities with complementary extensions.
Look for them in the [VS Code Marketplace](https://marketplace.visualstudio.com/).

## What's Next?

With VS Code mastery, explore advanced Foam topics:

1. **[[recommended-extensions]]** - See complementary extensions to improve your note taking experience
2. **[[publish-to-github-pages]]** - Share your knowledge base

[tags]: ../features/tags.md 'Tags'
[recommended-extensions]: recommended-extensions.md 'Recommended Extensions'
[publish-to-github-pages]: ../publishing/publish-to-github-pages.md 'GitHub Pages'

---

### User Getting Started Installation (`docs/user/getting-started/installation.md`)

# Installation

Getting started with Foam is straightforward. This guide will walk you through installing everything you need to begin your knowledge management journey.

## Step 1: Install Visual Studio Code

Foam is built on VS Code, Microsoft's free, open-source code editor. You can download it at https://code.visualstudio.com/

### Why VS Code?

VS Code provides:

- Excellent Markdown editing capabilities
- Rich extension ecosystem
- Cross-platform compatibility
- Integrated terminal and Git support
- Customizable interface and shortcuts

To learn more about using VS Code with Foam, check [[get-started-with-vscode]]

## Step 2: Install the Foam Extension

The Foam extension adds knowledge management superpowers to VS Code.

1. **Open VS Code**
2. **Click the Extensions icon** in the sidebar (or press `Ctrl+Shift+X` / `Cmd+Shift+X`)
3. **Search for "Foam"** in the extensions marketplace
4. **Click "Install"** on the official Foam extension by Foam Team
5. **Reload VS Code** when prompted

### What the Foam Extension Provides

- Wikilink auto-completion and navigation
- Backlink discovery and panel
- Graph visualization
- Powerful note template engine
- Daily notes functionality

## Step 3: Install Recommended Extensions

While Foam works on its own, it is focused on the networking aspect of your notes. You might want to install additional extensions to improve the editing experience or the functionality of your notes.

### Useful Extensions

- **Markdown All in One** - Rich Markdown editing features. Highly recommended.

Other extensions:

- **Spell Right** - Spell checking for your notes
- **Paste Image** - Easily insert images from clipboard
- **Todo Tree** - Track TODO items across your workspace

## Optional: Install the Foam CLI

The Foam CLI lets you work with your workspace from the terminal — search notes, manage tags, create daily notes, and more — without opening VS Code.

```bash
npm install foam-cli
```

Once installed, run `foam --help` to see available commands, or see the [[cli|CLI documentation]] for details.

## What's Next?

Now that Foam is installed, you're ready to:

1. **[[first-workspace]]** - Set up your knowledge base structure
2. **[[get-started-with-vscode]]** - Learn how to use VS Code for note taking
3. **[[note-taking-in-foam]]** - Write your first Markdown notes
4. **[[navigation]]** - Connect your thoughts with wikilinks
5. **[[graph-view]]** - Visualize your knowledge network

## Getting Help

If you encounter issues:

- Check the [[frequently-asked-questions]] for common problems
- Visit the [Foam Community Discord](https://discord.com/invite/HV2tn2FpEk)
- Browse [GitHub Issues](https://github.com/foambubble/foam/issues) for known problems
- Ask questions in [GitHub Discussions](https://github.com/foambubble/foam/discussions)

[get-started-with-vscode]: get-started-with-vscode.md 'Using Foam with VS Code Features'
[first-workspace]: first-workspace.md 'Creating Your First Workspace'
[note-taking-in-foam]: note-taking-in-foam.md 'Note-Taking in Foam'
[navigation]: navigation.md 'Navigation in Foam'
[graph-view]: ../features/graph-view.md 'Graph Visualization'
[frequently-asked-questions]: ../frequently-asked-questions.md 'Frequently Asked Questions'
[cli]: ../tools/cli.md 'Foam CLI'

---

### User Getting Started Keyboard Shortcuts (`docs/user/getting-started/keyboard-shortcuts.md`)

# Keyboard Shortcuts

Here are some keyboard shortcuts you'll love when editing your notes.

This works best if you can see the result in the preview panel, run the `Markdown: Open Preview to the Side` command.

You can use either the name or the id to find each shortcut in the settings (File > Preferences > Keyboard Shortcuts) and find out what it is bound to on your system and change it according to your liking.

| Shortcut       | Name            | ID                                      | Extension           | Use                                 |
| -------------- | --------------- | --------------------------------------- | ------------------- | ----------------------------------- |
| `alt+c`        | \-              | markdown.extension.checkTaskList        | Markdown All in One | Toggle TODO items.                  |
| `cmd+b`        | \-              | markdown.extension.editing.toggleBold   | Markdown All in One | Make selection bold.                |
| `cmd+i`        | \-              | markdown.extension.editing.toggleItalic | Markdown All in One | Make selection italic.              |
| `ctrl+shift+f` | Format Document | editor.action.formatDocument            | Base                | Format tables                       |
| `cmd+shift+f`  | Find files      | workbench.action.findInFiles            | Base                | Search in workspace.                |
| `cmd+shift+e`  | Show Explorer   | workbench.view.explorer                 | Base                | Show the file explorer.             |
| `cmd+alt+v`    | Paste Image     | extension.pasteImage                    | Paste Image         | Paste an image from your clipboard. |

---

### User Getting Started Navigation (`docs/user/getting-started/navigation.md`)

# Navigation in Foam

Navigation is where Foam truly shines. Unlike traditional file systems or notebooks, Foam lets you move through your knowledge by following connections between ideas. This guide will teach you how to navigate efficiently using wikilinks, backlinks, and other powerful features.

_[📹 Watch: Mastering navigation in Foam]_

## Understanding Wikilinks

Wikilinks are the backbone of Foam navigation. They connect your thoughts and let you jump between related concepts instantly.

### Basic Wikilink Syntax

```markdown
I'm learning about [[Machine Learning]] and its applications in [[Data Science]].

This reminds me of my notes on [[Python Programming]] from yesterday.
```

When you type `[[`, Foam shows you a list of existing notes to link to. If the note doesn't exist, Foam creates a placeholder that you can click to create the note later.

### Wikilink Variations

**Link to a specific heading:**

```markdown
See the [[Project Management#Risk Assessment]] section for details.
```

**Link to a specific block:**

```markdown
See the [[Project Management#^block-id]] paragraph for details.
```

**Link with alias:**

```markdown
According to [[Einstein, Albert|Einstein]], imagination is more important than knowledge.
```

### Autocomplete and Link Assistance

Foam provides intelligent autocomplete when creating links:

1. **Type `[[`** - Foam shows a dropdown of existing notes
2. **Start typing** - The list filters to matching notes
3. **Use arrow keys** to navigate suggestions
4. **Press Enter** to insert the selected link

## The Foam Graph

For a visual overview of your knowledge base, Foam offers a [[graph-view]]. This feature renders your notes as nodes and the links between them as connections, creating an interactive map of your thoughts.

_[📹 Watch: Navigation with the Foam Graph]_

### Using the Graph

1.  **Open the Command Palette** (`Ctrl+Shift+P` / `Cmd+Shift+P`)
2.  **Run the "Foam: Show Graph" command**
3.  The graph will open in a new panel. You can:

- **Click on a node** to navigate to that note.
- **Pan and zoom** to explore different areas of your knowledge base.
- **See how ideas cluster** and identify central concepts.

## Backlinks: The Power of Reverse Navigation

Backlinks show you which notes reference the current note. This creates a web of knowledge where ideas naturally connect.

### Viewing Backlinks

1. **Open any note**
2. **Look for the "Connections" panel** in the sidebar
3. **See all notes that link to your current note**
4. **Click any backlink** to jump to that note

## Quick Navigation Features

### Command Palette Navigation

Press `Ctrl+Shift+P` / `Cmd+Shift+P` and try these commands:

- **"Foam: Open Random Note"** - Discover forgotten knowledge
- **"Foam: Open Daily Note"** - Quick access to today's notes
- **"Go to File"** (`Ctrl+P` / `Cmd+P`) - Fast file opening
- **"Go to Symbol"** (`Ctrl+Shift+O` / `Cmd+Shift+O`) - Jump to headings within a note

### File Explorer Integration

The VS Code file explorer shows your note structure:

- **Click any `.md` file** to open it
- **Use the search box** to filter files
- **Right-click** for context menus (rename, delete, etc.)

Foam also supports the Note Explorer, which is like the file explorer, but centered around the Foam metadata.

### Quick Open

Press `Ctrl+P` / `Cmd+P` and start typing:

- **File names** - `machine` finds "machine-learning.md"
- **Partial paths** - `daily/2025` finds daily notes from 2025
- **Recent files** - Empty search shows recently opened files

## Link Management and Maintenance

### Finding Broken Links - Placeholders

In Foam broken links are considered placeholders for future notes.
Placeholders (references to non-existent notes) appear differently:

- In editor: `[[missing-note]]` will be highlighted a different color
- In preview: Shows as regular text or with special styling

Clicking on a placeholder in the editor will create the corresponding note.

**To find all placeholders:**

You can find placeholders by looking at the `Placeholders` treeview.

### Renaming and Moving Notes

When you rename a note file:

1. **Use VS Code's rename function** (`F2` key)
2. **Foam automatically updates** all links to that note
3. **Check the "Problems" panel** for any issues

Currently you cannot rename whole folders.

## What's Next?

With navigation mastered, you're ready to:

1. **[Search and navigate notes](../recipes/search-and-navigate-notes.md)** - All the ways to find and browse notes
2. **[Explore the graph view](../features/graph-view.md)** - Visualize your knowledge network
3. **[Learn about backlinks](../features/backlinking.md)** - Master bidirectional linking
4. **[Set up templates](../features/templates.md)** - Standardize your note creation
5. **[Use tags effectively](../features/tags.md)** - Add another layer of organization

[graph-view]: ../features/graph-view.md 'Graph Visualization'

---

### User Getting Started Note Taking In Foam (`docs/user/getting-started/note-taking-in-foam.md`)

# Note-Taking in Foam

Effective note-taking is the foundation of any knowledge management system. In Foam, you'll write notes in Markdown, a simple and powerful format that's both human-readable and widely supported. This guide will teach you everything you need to know about writing great notes in Foam.

## Markdown Basics

Markdown is a lightweight markup language that uses simple syntax to format text. Here are the essentials:

### Headings

```markdown
# Heading 1 (Main Title)

## Heading 2 (Major Section)

### Heading 3 (Subsection)

#### Heading 4 (Minor Section)
```

### Text Formatting

```markdown
**Bold text**
_Italic text_
**_Bold and italic_**
~~Strikethrough~~
`Inline code`
```

### Lists

```markdown
## Unordered Lists

- First item
- Second item
  - Nested item
  - Another nested item

## Ordered Lists

1. First step
2. Second step
   1. Sub-step
   2. Another sub-step
```

### Links and Images

```markdown
[External link](https://example.com)

```

### Code Blocks

````markdown
```javascript
function greet(name) {
  return `Hello, ${name}!`;
}
```
````

### Tables

```markdown
| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Data 1   | Data 2   | Data 3   |
| Data 4   | Data 5   | Data 6   |
```

### Quotes and Dividers

```markdown
> This is a quote or important note
> It can span multiple lines

---

Use three dashes for horizontal dividers
```

_[📹 Watch: Markdown syntax essentials for note-taking]_

## Foam-Specific Features

Beyond standard Markdown, Foam adds several powerful features:

### Wikilinks

Connect your notes with double brackets:

```markdown
I'm reading about [[Project Management]] and its relationship to [[Personal Productivity]].

This connects to [[2025-01-25-daily-note]] where I first had this insight.
```

### Note Embedding

Include content from other notes via [[embeds]]:

```markdown
![[Project Management#Key Principles]]

This embeds the "Key Principles" section from the Project Management note.
```

### Tags

Organize your content with [[tags]]:

```markdown
#productivity #learning #foam

Tags can be anywhere in your note and help with organization and filtering.
```

Use nested tags for better organization:

```markdown
#work/projects/website
#learning/programming/javascript
#personal/health/exercise
```

Those tags will show as a tree structure in the [Tag Explorer](../features/tags.md)

### Note Properties (YAML Front Matter)

Add metadata to your notes:

```markdown
---
title: 'Advanced Note-Taking Strategies'
tags: [productivity, learning, methods]
created: 2025-01-25
modified: 2025-01-25
status: draft
---

# Advanced Note-Taking Strategies

Your note content goes here...
```

## Writing Effective Notes

### The Atomic Principle

Each note should focus on one concept or idea:

**Good Example:**

```markdown
# The Feynman Technique

A learning method where you explain a concept in simple terms as if teaching it to someone else.

## Steps

1. Choose a topic to learn
2. Explain it in simple terms
3. Identify gaps in understanding
4. Simplify and use analogies

## Why It Works

- Forces active engagement with material
- Reveals knowledge gaps quickly
- Improves retention through teaching

Related: [[Active Learning]] [[Study Methods]]
```

**Avoid:**
Mixing multiple unrelated concepts in one note.

### Use Descriptive Titles

Your note titles should clearly indicate the content:

**Good:** `REST API Design Principles`
**Good:** `Meeting Notes - Product Roadmap Review 2025-01-25`
**Avoid:** `Stuff I Learned Today`
**Avoid:** `Notes`

### Link Generously

Don't hesitate to create links, even to notes that don't exist yet:

```markdown
# Machine Learning Fundamentals

Machine learning is a subset of [[Artificial Intelligence]] that focuses on creating algorithms that can learn from [[Data]].

Key concepts include:

- [[Supervised Learning]]
- [[Unsupervised Learning]]
- [[Neural Networks]]
- [[Feature Engineering]]

This connects to my work on [[Customer Behavior Analysis]] and [[Predictive Analytics]].
```

Foam will create placeholder pages for missing notes, making it easy to fill in knowledge gaps later.

## Keyboard Shortcuts

Essential VS Code shortcuts for note-taking:

| Shortcut                       | Action                |
| ------------------------------ | --------------------- |
| `Ctrl+N` / `Cmd+N`             | New file              |
| `Ctrl+S` / `Cmd+S`             | Save file             |
| `Ctrl+P` / `Cmd+P`             | Quick file open       |
| `Ctrl+Shift+P` / `Cmd+Shift+P` | Command palette       |
| `Ctrl+K V` / `Cmd+K V`         | Open Markdown preview |
| `Ctrl+[` / `Cmd+[`             | Decrease indent       |
| `Ctrl+]` / `Cmd+]`             | Increase indent       |
| `Alt+Z` / `Option+Z`           | Toggle word wrap      |

## What's Next?

Now that you understand note-taking basics:

1. **[[navigation]]** - Learn to move efficiently between notes with wikilinks
2. **[Explore the graph view](../features/graph-view.md)** - Visualize the connections in your knowledge base
3. **[Set up templates](../features/templates.md)** - Create reusable note structures
4. **[Use daily notes](../features/daily-notes.md)** - Establish a daily capture routine

[navigation]: navigation.md 'Navigation in Foam'
[tags]: ../features/tags.md 'Tags'
[embeds]: ../features/embeds.md 'Note Embeds'

---

### User Getting Started Recommended Extensions (`docs/user/getting-started/recommended-extensions.md`)

# Recommended Extensions

These extensions defined in `.vscode/extensions.json` are automatically installed when you accept the workspace's recommended extensions.

This list is subject to change.

- [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode)
- [Markdown All In One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one)
- [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)

## Extensions For Additional Features

These extensions are not defined in `.vscode/extensions.json`, but have been used by others and shown to play nice with Foam.

- [Emojisense](https://marketplace.visualstudio.com/items?itemName=bierner.emojisense) (provides emoji autocomplete and suggestions in markdown files)
- [Markdown Emoji](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-emoji) (adds `:smile:` syntax support, works with emojisense to provide autocomplete for this syntax)
- [Mermaid diagrams Support](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart) (adds syntax highlighting for Mermaid code blocks in markdown and renders Mermaid diagrams in markdown preview)
- [Excalidraw whiteboard and sketching tool integration](https://marketplace.visualstudio.com/items?itemName=pomdtr.excalidraw-editor) (create and edit hand-drawn style diagrams and sketches directly in VS Code)
- [VSCode PDF Viewing](https://marketplace.visualstudio.com/items?itemName=tomoki1207.pdf) (view PDF files directly within VS Code without external applications)
- [Project Manager](https://marketplace.visualstudio.com/items?itemName=alefragnani.project-manager) (easily switch between multiple projects and workspaces)
- [Markdown Extended](https://marketplace.visualstudio.com/items?itemName=jebbs.markdown-extended) (extended markdown syntax support with additional formatting options - use with `kbd` option disabled as it conflicts with wikilinks)
- [GitDoc](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gitdoc) (automatic git commits for easy version management and backup of your notes)
- [Todo Tree](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree) (scans workspace for TODO, FIXME, and other comment tags, displaying them in a tree view and editor gutter)

---

### User Getting Started Sync Notes (`docs/user/getting-started/sync-notes.md`)

# Sync notes with source control

Source control is a way to precisely manage the history and content of a directory of files.
Often used for program code, this feature is very useful for note taking as well.

There are (too) many ways to commit your changes to source control:

- Using VS Code's own git integration
  - The quick and easy way is to use the `Git: Commit All` command after editing files. The default Foam workspace settings will stage & sync all of your changes to the remote:
- Using GitDoc for [[automatic-git-syncing]]
- Whatever way you like to do it (CLI?)

[automatic-git-syncing]: ../recipes/automatic-git-syncing.md 'Automatically Sync with Git'

---

### User Publishing Generate Gatsby Site (`docs/user/publishing/generate-gatsby-site.md`)

# Generate a site using Gatsby

## Using foam-gatsby-template

You can use [foam-gatsby-template](https://github.com/mathieudutour/foam-gatsby-template) to generate a static site to host it online on GitHub or [Vercel](https://vercel.com).

### Publishing your foam to GitHub pages

It comes configured with GitHub actions to auto deploy to GitHub pages when changes are pushed to your main branch.

### Publishing your foam to Vercel

When you're ready to publish, run a local build.

```bash
cd _layouts
npm run build
```

Remove `public` from your .gitignore file then commit and push your public folder in `_layouts` to GitHub.

Log into your Vercel account. (Create one if you don't have it already.)

Import your project. Select `_layouts/public` as your root directory and click **Continue**. Then name your project and click **Deploy**.

That's it!

## Using foam-template-gatsby-kb

You can use another template [foam-template-gatsby-kb](https://github.com/hikerpig/foam-template-gatsby-kb), and host it on [Vercel](https://vercel.com) or [Netlify](https://www.netlify.com/).

## Using foam-template-gatsby-theme-primer-wiki

You can use another template [foam-template-gatsby-theme-primer-wiki](https://github.com/theowenyoung/foam-template-gatsby-theme-primer-wiki), ([Demo](https://demo-wiki.owenyoung.com/)), and host it on Github Pages, [Vercel](https://vercel.com) or [Netlify](https://www.netlify.com/).

---

### User Publishing Math Support With Katex (`docs/user/publishing/math-support-with-katex.md`)

# Katex Math Rendering

Apart from using the method mentioned in [[math-support-with-mathjax]], we can also use KaTeX to render our math equations in Foam. The caveat is: we can't rely on GitHub Pages to host and deploy our website anymore, because the plugin we'll be using to let Jekyll support KaTeX doesn't play well together with GitHub Pages.

The alternative solution is to using [[publish-to-vercel]] for building and publishing our website, so before you start integrating KaTeX into your Foam project, please follow the instructions to host your Foam workspace on [[publish-to-vercel]] first.

## Adding required plugins

Add the plugin `jekyll-katex` to your Foam workspace's `_config.yml` and `Gemfile` if you haven't done so already. For detailed instructions, please refer to the `#Adding a _config.yml` and `#Adding a Gemfile` in [[publish-to-vercel]].

## Loading KaTeX JS and CSS

Because we are using KaTeX to render math, we will also need to import KaTeX's JS and CSS files from CDN. The official method to load these files is documented at: [KaTeX/KaTeX#starter-template](https://github.com/KaTeX/KaTeX#starter-template). In our case, we will need to add the following code snippet to our `_layouts/page.html`:

```html

--- layout: default ---

<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.css"
  integrity="sha384-AfEj0r4/OFrOo5t7NnNe46zW/tFgW6x/bCJG8FqQCEo3+Aro6EYUG4+cU+KJWu/X"
  crossorigin="anonymous"
/>


<script
  defer
  src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js"
  integrity="sha384-g7c+Jr9ZivxKLnZTDUhnkOnsh30B4H0rpLUpJ4jAIKs4fnJI+sEnkvrMWph2EDg4"
  crossorigin="anonymous"
></script>


<script
  defer
  src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/contrib/auto-render.min.js"
  integrity="sha384-mll67QQFJfxn0IYznZYonOWZ644AWYC+Pt2cHqMaRhXVrursRwvLnLaebdGIlYNa"
  crossorigin="anonymous"
  onload="renderMathInElement(document.body);"
></script>


```

## Adding liquid tags to wrap page content

The plugin `jekyll-katex` focuses on rendering:

- Single math equations wrapped inside `katex` liquid tags like {% raw %}`{% katex %} ... {% endkatex %}`{% endraw %}.
- Or multiple math equations in paragraphs wrapped inside {% raw %}`{% katexmm %} ... {% endkatexmm %}`{% endraw %}.

In our case, we'll be using the latter tag to wrap our {% raw %}`{{ content }}`{% endraw %}. Wrap {% raw %}`{{ content }}`{% endraw %} in the liquid tags inside `_layouts/page.html` like so:

```html



{% raw %}{% katexmm %} {{ content }} {% endkatexmm %}{% endraw %}

```

## Render equations in Foam's homepage as well

You may have noticed that we only made modifications to the template `_layouts/page.html`, which means that `_layouts/home.html` won't have KaTeX support. If you wan't to render math in Foam's home page, you'll need to make the same modifications to `_layouts/home.html` as well.

Finally, if all goes well, then our site hosted on Vercel will support rendering math equations with KaTeX after committing these changes to GitHub. Here's a demo of the default template with KaTeX support: [Foam Template with KaTeX support](https://foam-template.vercel.app/).

[math-support-with-mathjax]: math-support-with-mathjax.md 'Math Support'
[publish-to-vercel]: publish-to-vercel.md 'Publish to Vercel'

---

### User Publishing Math Support With Mathjax (`docs/user/publishing/math-support-with-mathjax.md`)

---
layout: mathjax
---

# Math Support

Published Foam pages don't support math formulas by default. To enable this feature, you can add the following code snippet to the end of `_layouts/page.html`:

```html
<script
  src="https://cdn.jsdelivr.net/npm/mathjax@2/MathJax.js?config=TeX-AMS-MML_HTMLorMML"
  type="text/javascript"
></script>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
      tex2jax: {
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre'],
          inlineMath: [['$','$']]
      }
  });
</script>
```

This approach uses the [MathJax](https://www.mathjax.org/) library to render anything delimited by `$` (customizable in the snippet above) pairs to inline math and `$$` to blocks of math (like a html div tag) using with the AMS-LaTeX dialect embedded within MathJax.

Example of inline math using `$...$`:

`$e^{i \pi}+1=0$`, becomes $e^{i \pi}+1=0$

Example of a math block using `$$...$$`:

`$$ f_{\mathbf{X}}\left(x_{1}, \ldots, x_{k}\right)=\frac{\exp \left(-\frac{1}{2}(\mathbf{x}-\boldsymbol{\mu})^{\mathrm{T}} \mathbf{\Sigma}^{-1}(\mathbf{x}-\boldsymbol{\mu})\right)}{\sqrt{(2 \pi)^{k}|\mathbf{\Sigma}|}} $$`

Becomes:

$$ f*{\mathbf{X}}\left(x*{1}, \ldots, x\_{k}\right)=\frac{\exp \left(-\frac{1}{2}(\mathbf{x}-\boldsymbol{\mu})^{\mathrm{T}} \mathbf{\Sigma}^{-1}(\mathbf{x}-\boldsymbol{\mu})\right)}{\sqrt{(2 \pi)^{k}|\mathbf{\Sigma}|}} $$

## Alternative approaches

There are other dialects of LaTeX (instead of AMS), and other JavaScript rendering libraries you may want to use. In a future version of Foam, we may support KaTeX syntax out of the box, but at this time, these integrations are left as an exercise to the user.

## Why don't my Math expressions work on my Foam's home page?

If you want the index page of your Foam site to render maths, you'll need to add that to `_layouts/home.html` as well, or change the layout of the index page to be "page" instead of "home" by putting this Front Matter on the top of your `readme.md/index.md`:

```
---
layout: page
---

# Your normal title here
```

Reference: [How to support latex in github-pages](https://stackoverflow.com/questions/26275645/how-to-support-latex-in-github-pages)

---

### User Publishing Publish To Azure Devops Wiki (`docs/user/publishing/publish-to-azure-devops-wiki.md`)

# Publish to Azure DevOps Wiki

Publish your Foam workspace as an Azure DevOps wiki.

[Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) is Microsoft's collaboration software for software development teams, formerly known as Team Foundation Server (TFS) and Visual Studio Team Services. It is available as an on-premise or SaaS version. The following recipe was tested with the SaaS version, but should work the same way for the on-premise.

The following recipe is written with the assumption that you already have an [Azure DevOps](https://azure.microsoft.com/en-us/services/devops/) project.

## Setup a Foam workspace

1. Generate a Foam workspace using the [foam-template project](https://github.com/foambubble/foam-template).
2. Change the remote to a git repository in Azure DevOps (Repos -> Import a Repository -> Add Clone URL with Authentication), or copy all the files into a new Azure DevOps git repository.
3. Define which document will be the wiki home page. To do that, create a file called `.order` in the Foam workspace root folder, with first line being the document filename without `.md` extension. For a project created from the Foam template, the file would look like this:

```
readme
```

4. Push the repository to remote in Azure DevOps.

## Publish repository to a wiki

1. Navigate to your Azure DevOps project in a web browser.
2. Choose **Overview** > **Wiki**. If you don't have wikis for your project, choose **Publish code as a wiki** on welcome page.
3. Choose repository with your Foam workspace, branch (usually `master` or `main`), folder (for workspace created from foam-template it is `/`), and wiki name, and press **Publish**.

A published workspace looks like this:



There is default table of contents pane to the left of the wiki content. Here, you'll find a list of all directories that are present in your Foam workspace, and all wiki pages. Page names are derived from files names, and they are listed in alphabetical order. You may reorder pages by adding filenames without `.md` extension to `.order` file.

_Note that first entry in `.order` file defines wiki's home page._

## Update wiki

While you are pushing changes to GitHub, you won't see the wiki updated if you don't add Azure as a remote. You can push to multiple repositories simultaneously.

1.  First open a terminal and check if Azure is added running: `git remote show origin`. If you don't see Azure add it in the output then follow these steps.
2.  Rename your current remote (most likely named origin) to a different name by running: `git remote rename origin main`
3.  You can then add the remote for your second remote repository, in this case, Azure. e.g `git remote add azure https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes`. You can get it from: Repos->Files->Clone and copy the URL.
4.  Now, you need to set up your origin remote to push to both of these. So run: `git config -e` and edit it.
5.  Add the `remote origin` section to the bottom of the file with the URLs from each remote repository you'd like to push to. You'll see something like that:

```bash
[core]
 ...
  (ignore this part)
  ...
[branch "main"]
 remote = github
 merge = refs/heads/main
[remote "github"]
 url = git@github.com:username/repo.git
 fetch = +refs/heads/*:refs/remotes/github/*
[remote "azure"]
 url = https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes
 fetch = +refs/heads/*:refs/remotes/azure/*
[remote "origin"]
 url = git@github.com:username/repo.git
 url = https://<YOUR_ID>@dev.azure.com/<YOUR_ID>/foam-notes/_git/foam-notes
```

6.  You can then push to both repositories by: `git push origin main` or a single one using: `git push github main` or `git push azure main`

For more information, read the [Azure DevOps documentation](https://docs.microsoft.com/en-us/azure/devops/project/wiki/publish-repo-to-wiki).

---

### User Publishing Publish To Github Pages (`docs/user/publishing/publish-to-github-pages.md`)

# GitHub Pages

1. In VSCode workspace settings set `"foam.edit.linkReferenceDefinitions": "withoutExtensions"`
2. Execute the “Foam: Lint Workspace” command from the command palette.
3. [Turn **GitHub Pages** on in your repository settings](https://guides.github.com/features/pages/).
   - The default GitHub Pages template is called [Primer](https://github.com/pages-themes/primer). See Primer docs for how to customise html layouts and templates.
   - GitHub Pages is built on [Jekyll](https://jekyllrb.com/), so it supports things like permalinks, front matter metadata etc.

## How to publish locally

If you want to test your published foam, follow the instructions:

- <https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/creating-a-github-pages-site-with-jekyll>
- <https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/testing-your-github-pages-site-locally-with-jekyll>

Assuming you have installed ruby/jekyll and the rest:

- `touch Gemfile`
  - open the file and paste the following:

```
source 'https://rubygems.org'

gem "github-pages", "VERSION"
```

replacing `VERSION` with the latest from <https://rubygems.org/gems/github-pages> (e.g. `gem "github-pages", "209"`)

- `bundle`
- `bundle exec jekyll 3.9.0 new .`
- edit the `Gemfile` according to the instructions at [Creating Your Site](https://docs.github.com/en/free-pro-team@latest/github/working-with-github-pages/creating-a-github-pages-site-with-jekyll#creating-your-site) Point n.8
- `bundle exec jekyll serve`

## Other templates

There are many other templates which also support publish your foam workspace to github pages

- gatsby-digital-garden
  - [repo](https://github.com/mathieudutour/gatsby-digital-garden)
  - [demo-website](https://mathieudutour.github.io/gatsby-digital-garden/)
- foam-mkdocs-template
  - [repo](https://github.com/Jackiexiao/foam-mkdocs-template)
  - [demo-website](https://jackiexiao.github.io/foam/)
- foam-jekyll-template
  - [repo](https://github.com/hikerpig/foam-jekyll-template)
  - [demo-website](https://hikerpig.github.io/foam-jekyll-template/)

---

### User Publishing Publish To Github (`docs/user/publishing/publish-to-github.md`)

# Publish to GitHub

The standard [foam-template](https://github.com/foambubble/foam-template) is ready to be published to GitHub, and GitHub pages.

## Enable navigation in GitHub

To allow navigation from within the GitHub repo, make sure to generate the link references, by setting

- `Foam › Edit: Link Reference Definitions` -> `withExtensions`

See [[link-reference-definitions]] for more information.

## Customising the style

You can edit `assets/css/style.scss` to change how published pages look.

[link-reference-definitions]: ../features/link-reference-definitions.md 'Link Reference Definitions'

---

### User Publishing Publish To Gitlab Pages (`docs/user/publishing/publish-to-gitlab-pages.md`)

# GitLab Pages

You don't have to use GitHub to serve Foam pages. You can also use GitLab.

Gitlab pages can be kept private for private repo, so that your notes are still private.

## Setup a project

### Generate the directory from GitHub

Generate a solution using the [Foam template](https://github.com/foambubble/foam-template).

Change the remote to GitLab, or copy all the files into a new GitLab repo

## Publishing pages with Gatsby

### Setup the Gatsby config

Add a .gatsby-config.js file where:

- `$REPO_NAME` correspond to the name of your gtlab repo.
- `$USER_NAME` correspond to your gitlab username.

```
/* Detailed source-code truncated for AI context efficiency. */
```

And a `package.json` file containing:

```json
{
  "private": true,
  "name": "wiki",
  "version": "1.0.0",
  "license": "MIT",
  "scripts": {
    "develop": "gatsby develop -H 0.0.0.0",
    "start": "gatsby develop -H 0.0.0.0",
    "build": "gatsby build",
    "clean": "gatsby clean",
    "serve": "gatsby serve",
    "test": "echo test"
  },
  "dependencies": {
    "@primer/react": "^34.1.0",
    "@primer/css": "^17.5.0",
    "foam-cli": "^0.11.0",
    "gatsby": "^3.12.0",
    "gatsby-plugin-manifest": "^3.12.0",
    "gatsby-plugin-robots-txt": "^1.6.9",
    "gatsby-plugin-sitemap": "^5.4.0",
    "gatsby-source-filesystem": "^3.12.0",
    "gatsby-theme-primer-wiki": "^1.14.5",
    "react": "^17.0.2",
    "react-dom": "^17.0.2"
  }
}
```

The theme will be based on [gatsby-theme-primer-wiki](https://github.com/theowenyoung/gatsby-theme-primer-wiki).

To test the theme locally first run `yarn install` and then use `gatsby develop` to serve the website.
See gatsby documentation for more details.

### Set-up the CI for deployment

Create a `.gitlab-ci.yml` file containing:

```yml
# To contribute improvements to CI/CD templates, please follow the Development guide at:
# https://docs.gitlab.com/ee/development/cicd/templates.html
# This specific template is located at:
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Pages/Gatsby.gitlab-ci.yml

image: node:latest

stages:
  - deploy

pages:
  stage: deploy
  # This folder is cached between builds
  # https://docs.gitlab.com/ee/ci/yaml/index.html#cache
  cache:
    paths:
      - node_modules/
      # Enables git-lab CI caching. Both .cache and public must be cached, otherwise builds will fail.
      - .cache/
      - public/
  script:
    - yarn install
    - ./node_modules/.bin/gatsby build --prefix-paths
  artifacts:
    paths:
      - public
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
```

This pipeline will now serve your website on every push to the main branch of your project.

## Publish with Jekyll

### Add a \_config.yaml

Add another file to the root directory (the one with `readme.md` in it) called `_config.yaml` (no extension)

```yaml
title: My Awesome Foam Project
baseurl: '' # the subpath of your site, e.g. /blog
url: '/' # the base hostname & protocol for your site
theme: jekyll-theme-minimal
plugins:
  - jekyll-optional-front-matter
optional_front_matter:
  remove_originals: true
defaults:
  - scope:
      path: '' # we need to add this to properly render layouts
    values:
      layout: 'default'
```

You can choose a theme if you want from places like [Jekyll Themes](https://jekyllthemes.io/)

### Add a Gemlock file

Add another file to the root directory (the one with `readme.md` in it) called `Gemfile` (no extension)

```ruby
source "https://rubygems.org"

gem "jekyll"
gem "jekyll-theme-minimal"
gem "jekyll-optional-front-matter"
```

Commit the file and push it to gitlab.

### Setup CI/CD

1. From the project home in GitLab click `Set up CI/CD`
2. Choose `Jekyll` as your template from the template dropdown
3. Click `commit`
4. Now when you go to CI / CD > Pipelines, you should see the code running

### Troubleshooting

- _Could not locate Gemfile_ - You didn't follow the steps above to [Add a Gemlock file](#add-a-gemlock-file)
- _Conversion error: Jekyll::Converters::Scss encountered an error while converting_ You need to reference a theme.
- _Pages are running in CI/CD, but I only ever see `test`, and never deploy_ - Perhaps you've renamed the main branch (from master) - check the settings in `.gitlab-ci.yml` and ensure the deploy command is running to the branch you expect it to.
- _I deployed, but my .msd files don't seem to be being converted into .html files_ - You need a gem that GitHub installs by default - check `gem "jekyll-optional-front-matter"` appears in the `Gemfile`

---

### User Publishing Publish To Netlify With Eleventy (`docs/user/publishing/publish-to-netlify-with-eleventy.md`)

# Publish to Netlify with Eleventy

You can use [foam-eleventy-template](https://github.com/juanfrank77/foam-eleventy-template) to generate a static site with [Eleventy](https://www.11ty.dev/), and host it online on [Netlify](https://www.netlify.com/).

With this template you can

- Have control over what to publish and what to keep private
- Customize the styling of the site to your own liking

## Publishing your foam

When you're ready to publish, import the GitHub repository you created with **foam-eleventy-template** into your Netlify account. (Create one if you don't have it already.)

Once that's done, all you have to do is make changes to your workspace in VS Code and push them to the main branch on GitHub. Netlify will recognize the changes, deploy them automatically and give you a link where your Foam is published.

That's it!

You can now see it online and use that link to share it with your friends, so that they can see it too.

---

### User Publishing Publish To Vercel (`docs/user/publishing/publish-to-vercel.md`)

# Publish to Vercel

This #recipe shows you how to deploy the default Foam website template to Vercel.

[Vercel](https://vercel.com/) is a static website hosting solution similar to GitHub Pages (see [[publish-to-github-pages]]).

## Setting up the project

### Using Foam's template

Generate a GitHub repository using the default [Foam template](https://github.com/foambubble/foam-template), this will be the workspace that we will be deploying with Vercel. This workspace is a barebone Jekyll source website, which means we can customize and install plugins just like any other Jekyll websites.

As we won't be using GitHub Pages, we will be adding a few configuration files in order to help Vercel pick up on how to build our site.

### Adding a `_config.yml`

First, we'll need to add a `_config.yml` at the root directory. This is the Jekyll configuration file. In here, we will set the site's title, theme, repository and permalink options, and also tell Jekyll what plugins to use:

```yaml
# _config.yml
title: Foam
# All the plugins we will be installing now that we won't be using GitHub Pages
plugins:
  - jekyll-katex # optional
  - jekyll-default-layout
  - jekyll-relative-links
  - jekyll-readme-index
  - jekyll-titles-from-headings
  - jekyll-optional-front-matter
# The default Jekyll theme we will be using
theme: jekyll-theme-primer
# The GitHub repository that we are hosting our foam workspace from
repository: user/repo
# Generate permalinks in format specified in: https://jekyllrb.com/docs/permalinks/#built-in-formats
permalink: pretty
```

The `theme` specifies a theme for our deployed Jekyll website. The default GitHub Pages template is called [Primer](https://github.com/pages-themes/primer). See Primer docs for how to customise html layouts and templates. We can also choose a theme if you want from places like [Jekyll Themes](https://jekyllthemes.io/).

The `plugins` specifies a list of Jekyll plugins that we will be installing in the next section. As we won't be using GitHub Pages, we'll need to install these plugins that GitHub Pages installs for us under the hood.

_If you want to use LaTeX rendered with KaTeX (which is what the plugin `jekyll-katex` does), you can specify it here. And yes, one of the benefits of deploying with Vercel is that we can use KaTeX to render LaTeX! More on: [[math-support-with-katex]]_

### Adding a `Gemfile`

Next up, we'll create another new file called `Gemfile` in the root directory. This is where we will let Vercel know what plugins to install when building our website.

In our `Gemfile`, we need to specify our Ruby packages:

```ruby
# Gemfile
source "https://rubygems.org"
gem "jekyll"
gem "kramdown-parser-gfm"
gem "jekyll-theme-primer"
gem "jekyll-optional-front-matter"
gem "jekyll-default-layout"
gem "jekyll-relative-links"
gem "jekyll-readme-index"
gem "jekyll-titles-from-headings"
gem "jekyll-katex"  # Optional, the package that enables KaTeX math rendering
```

### Enable math rendering with KaTeX (optional)

Besides adding the plugin `jekyll-katex` in `_config.yml` and `Gemfile`, we'll also have to follow the guides in [[math-support-with-katex]] to let our site fully support using KaTeX to render math equations.

### Committing changes to GitHub repo

Finally, commit the newly created files to GitHub.

## Importing project to Vercel

First, import our foam workspace (GitHub repository) to Vercel with [Vercel's _Import Git Repository_](https://vercel.com/import/git). Paste our GitHub repo's url and Vercel will automatically pull and analyze the tool we use to deploy our website. (In our case: Jekyll.)

Next, select the folder to deploy from if prompted. If we are using the default template, then Vercel will default to the root directory of our Foam workspace.

Finally, if all is successful, Vercel will show the detected framework: Jekyll. Press `Deploy` to proceed on publishing our project.



And now, Vercel will take care of building and rendering our foam workspace each time on push. Vercel will publish our site to `xxx.vercel.app`, we can also define a custom domain name for our Vercel website.

[publish-to-github-pages]: publish-to-github-pages.md 'GitHub Pages'
[math-support-with-katex]: math-support-with-katex.md 'Katex Math Rendering'

---

### User Recipes Add Images To Notes (`docs/user/recipes/add-images-to-notes.md`)

# Add images to your notes

This #recipe allows you to paste images on to your notes.

VScode (since
[1.79](https://code.visualstudio.com/updates/v1_79#_copy-external-media-files-into-workspace-on-drop-or-paste-for-markdown))
now has the ability to paste images from the clipboard, or drag-and-drop image
files, directly into markdown documents. The file will be created in the
workspace, and a link generated in Markdown format.

VSCode settings under `Markdown > Copy Files` and `Markdown > Editor > Drop` can
be used to configure where the files get placed in your workspace, how they're
named, how conflicts with existing files are handled, and more.

---

### User Recipes Automatic Git Syncing (`docs/user/recipes/automatic-git-syncing.md`)

# Automatically Sync with Git

With this #recipe you can regularly commit and push to git, to keep your repo in always synched.
You can also easily manipulate the git history to reduce clutter.

## Required Extensions

- [GitDoc](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gitdoc)

## Instructions

Click on the extension link above to see how to use it.

**For Foam specific needs, you can add a comment here by following the [contribution guide](https://github.com/foambubble/foam/blob/main/CONTRIBUTING.md).**

## Feedback and issues

- Feedback and issues with the extension should be reported to the authors themselves
- Feedback and issues with the integration of the extension in Foam can be reported in our [issue tracker](https://github.com/foambubble/foam/issues)

---

### User Recipes Automatically Expand Urls To Well Titled Links (`docs/user/recipes/automatically-expand-urls-to-well-titled-links.md`)

# Automatically Expand URLs to Well-Titled Links

With this #recipe you can convert a link to a fully-formed Markdown link, using the page's title as a display name. Useful for citations and creating link collections.

## Required Extensions

- [Markdown Link Expander](https://marketplace.visualstudio.com/items?itemName=skn0tt.markdown-link-expander) (not included in template)

Markdown Link Expander will scrape your URL's `<title>` tag to create a nice Markdown-style link.

## Instructions



1. Highlight desired URL
2. `Cmd` + `Shift` + `P`
3. `Expand URL to Markdown`
4. Profit

Tip: If you paste a lot of links, give the action a custom [key binding](https://code.visualstudio.com/docs/getstarted/keybindings)

## Feedback and issues

Have an idea for the extension? [Feel free to share! 🎉](https://github.com/Skn0tt/markdown-link-expander/issues)

---

### User Recipes Capture Notes With Drafts Pro (`docs/user/recipes/capture-notes-with-drafts-pro.md`)

# Capture Notes With Drafts Pro

With this #recipe you can create notes on your iOS device, which will automatically be imported into Foam.

## Context

- You use [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) to manage your notes
- You wish to adopt a practice such as [A writing inbox for transient and incomplete notes](https://notes.andymatuschak.org/A%20writing%20inbox%20for%20transient%20and%20incomplete%20notes)
- You wish to use [Drafts Pro](https://docs.getdrafts.com/) to capture quick notes into your Foam notes from your iOS device

## Other tools

- We assume you are familiar with how to use GitHub (if you are using Foam this is implicit)
- You have an iOS device with [Drafts](https://getdrafts.com/)
- You have upgraded to [Drafts Pro](https://docs.getdrafts.com/draftspro) (needed to edit actions).

## Instructions

1. [Create a new action in Drafts](https://docs.getdrafts.com/docs/actions/editing-actions)
2. Add a single [step](https://docs.getdrafts.com/actions/steps/) of type Script
3. Edit the script adding the code from the block below
4. Edit settings at the top of the script to suit your preferences
5. Set other Action options in Drafts as you wish
6. Save the Action
7. In GitHub [create a Personal Access Token](https://github.com/settings/tokens) and give it `repo` scope - make a note of the token
8. In Drafts create a note
9. Select the action you created in steps 1-6
10. On the first run you will need to add the following information:
    1. your GitHub username
    2. the repository name of your Foam repo
    3. the GitHub access token from step 7
    4. An author name
11. Check your GitHub repo for a commit
12. If you are publishing your Foam to the web you may want to edit your publishing configuration to exclude inbox files - as publishing (and method) is a user choice that is beyond the scope of this recipe

## Code for Drafts Action

```
/* Detailed source-code truncated for AI context efficiency. */
```

---

### User Recipes Capture Notes With Shortcuts And Github Actions (`docs/user/recipes/capture-notes-with-shortcuts-and-github-actions.md`)

# Capture Notes With Shortcuts and GitHub Actions

With this #recipe you can create notes on your iOS device, which will automatically be imported into Foam.

## Context

- You use [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) to manage your notes
- You wish to adopt a practice such as [A writing inbox for transient and incomplete notes](https://notes.andymatuschak.org/A%20writing%20inbox%20for%20transient%20and%20incomplete%20notes)
- You wish to use [Shortcuts](https://support.apple.com/guide/shortcuts/welcome/ios) to capture quick notes into your Foam notes from your iOS device

## Other tools

- We assume you are familiar with how to use GitHub (if you are using Foam this is implicit)
- You have an iOS device.

## Instructions

1. Setup the [`foam-capture-action`]() in your GitHub Repository, to be triggered by "Workflow dispatch" events.

```
name: Manually triggered workflow
on:
  workflow_dispatch:
    inputs:
      data:
        description: 'What information to put in the knowledge base.'
        required: true

jobs:
  store_data:
    runs-on: ubuntu-latest
    # If you encounter a 403 error from a workflow run, try uncommenting the following 2 lines (taken from: https://stackoverflow.com/questions/75880266/cant-make-push-on-a-repo-with-github-actions accepted answer)
    # permissions:
          # contents: write
    steps:
    - uses: actions/checkout@master
    - uses: anglinb/foam-capture-action@main
      with:
        {% raw %}
        capture: ${{ github.event.inputs.data }}
        {% endraw %}
    - run: |
        git config --local user.email "example@gmail.com"
        git config --local user.name "Your name"
        git commit -m "Captured from workflow trigger" -a
        git push -u origin master
```

2. In GitHub [create a Personal Access Token](https://github.com/settings/tokens) and give it `repo` scope - make a note of the token
3. Run this command to find your `workflow-id` to be used in the Shortcut.

```bash
curl \
  -H "Accept: application/vnd.github.v3+json" \
  -H "Authorization: Bearer <GITHUB_TOKEN>" \
    https://api.github.com/repos/<owner>/<repository>/actions/workflows
```

4. Copy this [Shortcut](https://www.icloud.com/shortcuts/57d2ed90c40e43a5badcc174ebfaaf1d) to your iOS devices and edit the contents of the last step, `GetContentsOfURL`

   - Make sure you update the URL of the shortcut step with the `owner`, `repository`, `workflow-id` (from the previous step)
   - Make sure you update the headers of the shortcut step, replaceing `[GITHUB_TOKEN]` with your Personal Access Token (from step 2)

5. Run the shortcut & celebrate! ✨ (You should see a GitHub Action run start and the text you entered show up in `inbox.md` in your repository.)

---

### User Recipes Diagrams In Markdown (`docs/user/recipes/diagrams-in-markdown.md`)

# Diagrams in Markdown

We have two alternative #recipe for displaying diagrams in markdown:

- [Diagrams in Markdown](#diagrams-in-markdown)
  - [Mermaid](#mermaid)
  - [Draw.io](#drawio)
    - [Using Draw.io](#using-drawio)

## Mermaid

You can use [Mermaid](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid) plugin to draw and preview diagrams in your content.

## Draw.io

[Draw.io](https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio) extension allows you to create, edit, and display your diagrams without leaving Visual Studio Code. The `.drawio.svg` or `.drawio.png` files can be automatically embedded and displayed in published Foams, no export needed. FYI, the diagram below was made using Draw.io! You can check the diagram [here](../../assets/images/diagram-drawio-demo.drawio.svg).



### Using Draw.io

1. Install [Draw.io](https://marketplace.visualstudio.com/items?itemName=hediet.vscode-drawio) VS Code extension.
2. Create a new `*.drawio.svg` or `*.drawio.png` file.
3. Start drawing your diagram. Once you done, save it.
4. Embed the diagram file as you embedding the image file, for example: ``

---

### User Recipes Export To Pdf (`docs/user/recipes/export-to-pdf.md`)

# Export to PDF

This #recipe shows how to export a note to PDF.

## Required extensions

- **[vscode-pandoc](https://marketplace.visualstudio.com/items?itemName=chrischinchilla.vscode-pandoc)**

## Required third-party tools

- [Pandoc](https://pandoc.org/installing.html)
- A [LaTeX distribution](https://www.latex-project.org/get/) such as TeXLive (Linux), MacTeX (MacOS), or MikTeX (Windows)

Check that Pandoc is installed by opening a terminal and running `pandoc --version`.

Check that Pandoc can produce PDFs with LaTeX by running the following in the terminal.

```
echo It is working > test.md
pandoc test.md -o test.pdf
```

## Instructions

1. Create a folder in your workspace named `.pandoc`. Take note of the full path to this directory. The rest of this recipe will refer to this path as `$WORKSPACE/.pandoc`.

2. Download the template file [`foam.latex`](https://raw.githubusercontent.com/Hegghammer/foam-templates/main/foam.latex) from [Hegghammer/foam-templates](https://github.com/Hegghammer/foam-templates) and place it in `$WORKSPACE/.pandoc`.

3. In VSCode, open `settings.json` for your user (or just for your workspace if you prefer), and add the following line:

```
"pandoc.pdfOptString": "--from=markdown+wikilinks_title_after_pipe --resource-path $WORKSPACE/.pandoc --template foam --listings",
```

Make sure to replace `$WORKSPACE/.pandoc` with the real full path to the `.pandoc` directory you created earlier.

4. Open a Foam note in VSCode.

5. Press `Ctrl` + `k`, `p`. Choose "pdf", and press `Enter`.

The PDF should look something like this:



## Options

If you include a name in the `author` parameter in the YAML of the Foam note, that name will feature in the PDF header on the top left.

If you don't want syntax highlighting and frames around the codeblocks, remove `--listings` from the `pandoc.pdfOptString` parameter in `settings.json`.

## Further customization

If you know some LaTeX, you can [tweak](https://bookdown.org/yihui/rmarkdown-cookbook/latex-template.html) the `foam.latex` template to your needs. Alternatively, you can supply another ready-made template such as [Eisvogel](https://github.com/Wandmalfarbe/pandoc-latex-template); just place the `TEMPLATE_NAME.latex` file in `$WORKSPACE/.pandoc`. You can also use all of Pandoc's [other functionalities](https://learnbyexample.github.io/customizing-pandoc/) by tweaking the `pandoc.pdfOptString` parameter in `settings.json`.

---

### User Recipes Generate Material For Mkdocs Site (`docs/user/recipes/generate-material-for-mkdocs-site.md`)

# Generate a site using the Material for MkDocs theme

Configuring a static-site generator (SSG) to publish your Foam provides access to functionality not available through Foam's default publishing mechanism. For example, compare the [original Foam documentation site](https://docs.foam.md/) with a [Material for MkDocs version](https://djplaner.github.io/foam-with-material-for-mkdocs/) created using the simple configuration detailed below. Try out the search functionality on the Material for MkDocs version. This [digital garden](https://djon.es/memex) and this [blog](https://djon.es/blog/) provide more advanced examples of Foam content published using Material for MkDocs.

The following explains how to configure the [Material for MkDocs theme](https://squidfunk.github.io/mkdocs-material/) for the [MkDocs SSG](https://www.mkdocs.org) to publish your Foam.

Like most SSGs (e.g. [Gatsby](https://www.gatsbyjs.com/) is another SSG that can be [used to publish your Foam](https://docs.foam.md/publishing/generate-gatsby-site/)) site content is accepted in the form of Markdown files. Like those produced by Foam. SSGs differ in the languages they are written in (MkDocs is Python, Gatsby is Javascript and React) and the features they provide. MkDocs and Material for MkDocs are designed to support project documentation. Gatsby is more general purpose and provides a nice feature set.

You choose your poison.

## Requirements

To use Material for MkDocs to publish your Foam you need:

- An existing Foam workspace with content.
- [Python installed on your computer](https://realpython.com/installing-python/).
- Some familiarity and comfort with using the command line on your computer.

## Instructions

Configuring Material for MkDocs to publish your Foam involves the following steps:

1. [Install Material for MkDocs and other requirements](#install-material-for-mkdocs-and-other-requirements).

   Install the Material for MkDocs theme, MkDocs, and other required Python modules.

2. [Configure Material for MkDocs for your Foam](#configure-material-for-mkdocs-for-your-foam).

   Create a `mkdocs.yml` file in the root of your Foam workspace directory. This file configures Material for MkDocs to work with your Foam.

3. [Preview and test your site locally](#preview-and-test-your-site-locally).

   Run MkDocs to preview and test your Material for MkDocs Foam site locally. Good for testing and local use.

4. [Further customise Material for MkDocs](#further-customise-material-for-mkdocs).

   Explore and leverage the additional configuration settings, possible customisations, and additional themes and plugins to customise your site to your needs.

5. [Publish your site](#publish-your-site).

   Publish your Material for MkDocs Foam site to the web for others to enjoy. There are many options for publishing your site, including GitHub, GitLab, Netlify, and others.

### Install Material for MkDocs and other requirements

Material for MkDocs provides [detailed installation instructions](https://squidfunk.github.io/mkdocs-material/getting-started/) which cover the full range of options for installing and configuring Material for MkDocs. The following is a summary of the recommended process.

1. Within your Foam workspace directory, create a [Python virtual environment](https://realpython.com/what-is-pip/#using-pip-in-a-python-virtual-environment)

   - `python -m venv .venv`
   - `source .venv/bin/activate` (Linux/Mac) or `.venv\Scripts\activate` (Windows)

2. Install Material for MkDocs

   - `pip install mkdocs-material`

3. Install additional Python modules

   - `pip install mkdocs-roamlinks-plugin`
   - `pip install mkdocs-exclude`

### Configure Material for MkDocs for your Foam

To configure Material for MkDocs for your Foam workspace, create a `mkdocs.yml` file in the root of your Foam workspace directory. Below you will find a sample `mkdocs.yml` file (adapted from the [foam-mkdocs-template repository](https://github.com/Jackiexiao/foam-mkdocs-template/tree/master)). Copy and paste it into your `mkdocs.yml` file, then edit it to suit your needs. In particular, don't forget to change the `site_name` and `site_url` to match your Foam workspace. Though this can be left a little later.

Material for MkDocs provides documentation on both [minimal](https://squidfunk.github.io/mkdocs-material/creating-your-site/#minimal-configuration) and [advanced](https://squidfunk.github.io/mkdocs-material/creating-your-site/#advanced-configuration) configuration of `mkdocs.yml`. Which are revisited in the [customise section below](#further-customise-your-site)

```yaml
site_name: My site # Change this to your site name
site_url: https://mydomain.org/mysite # change this
theme:
  name: material
  features:
    - navigation.expand
    - tabs
markdown_extensions:
  - attr_list
  - pymdownx.tabbed
  - nl2br
  - toc:
      permalink: '#'
      slugify: !!python/name:pymdownx.slugs.uslugify
  - admonition
  - codehilite:
      guess_lang: false
      linenums: false
  - footnotes
  - meta
  - def_list
  - pymdownx.arithmatex
  - pymdownx.betterem:
      smart_enable: all
  - pymdownx.caret
  - pymdownx.critic
  - pymdownx.details
  - pymdownx.inlinehilite
  - pymdownx.magiclink
  - pymdownx.mark
  - pymdownx.smartsymbols
  - pymdownx.superfences
  - pymdownx.tasklist
  - pymdownx.tilde
plugins:
  - search
  - roamlinks
  - exclude:
      glob:
        - '*.tmp'
        - '*.pdf'
        - '*.gz'
      regex:
        - '.*\.(tmp|bin|tar)$'
```

### Preview and test your site locally

MkDocs provides a live preview server allowing you to preview and test your Material for MkDocs Foam site. The server will continue to rebuid your site as you write.

The simplest method to use the preview service is to run the following command whilst in the rood directory of your Foam workspace:

```bash
mkdocs serve
```

See the Material for MkDocs site for more, including [how to run the preview server via docker](https://squidfunk.github.io/mkdocs-material/creating-your-site/#previewing-as-you-write)

### Further customise your site

Further customisation is available through expanding the configuration of Material for MkDocs, using additional MkDocs plugins, customising HTML/CSS, using Markdown extensions, writing your own Python scripts, and more.

For more on the available customisation paths, see the following:

- Material for MkDocs [Advanced configuration](https://squidfunk.github.io/mkdocs-material/creating-your-site/#advanced-configuration) or the [Set up section](https://squidfunk.github.io/mkdocs-material/setup/)

  For more configuration options to be included in your `mkdocs.yml` file, including customising: colours, fonts, language, icons, navigation, header, footer etc.

- Material for MkDocs [Customisation](https://squidfunk.github.io/mkdocs-material/customization/)

  For advice on enhancing the visual design of your site by customising and replacing provided HTML, CSS, and Javascript.

- Material for MkDocs [Reference](https://squidfunk.github.io/mkdocs-material/reference/)

  An overview of customisation methods that can be used directly within your Markdown files, including: admonitions, annotations, buttons, code blocks, content tabs, data tables, diagrams, grids, Mathematics, etc.

- a [catalog of 300 MkDocs projects and plugins](https://github.com/mkdocs/catalog#readme)

  For functionality and ideas not included in Material for MkDocs, including: additional themes, plugins, and extensions.

### Building and publishing your site

As a Static Site Generator (SSG), MkDocs generates a collection of static HTML and other types of files. Publishing your site involves building those HTML files and placing them onto your web server. The method will vary depending on your web server and hosting provider.

The MkDocs documentation site provides an explanation of the [simplest method to publish your site to any provider](https://www.mkdocs.org/user-guide/deploying-your-docs/#other-providers) using `mkdocs build` and `scp`.

The Material for MkDocs [publish page](https://squidfunk.github.io/mkdocs-material/publishing-your-site/) lists options for publishing to

- GitHub using [mkdocs](https://squidfunk.github.io/mkdocs-material/publishing-your-site/#with-mkdocs)

  Perhaps the simplest method, if you are already using GitHub to host your Foam workspace.

- GitHub using [GitHub actions](https://squidfunk.github.io/mkdocs-material/publishing-your-site/github-actions/)

  A more automated method of publishing your site to GitHub, using GitHub actions.

- [GitLab](https://squidfunk.github.io/mkdocs-material/publishing-your-site/#with-mkdocs)

- [Cloudflage pages](https://deborahwrites.com/guides/deploy-host-mkdocs/deploy-mkdocs-material-cloudflare/)

- [Netlify](https://deborahwrites.com/guides/deploy-host-mkdocs/deploy-mkdocs-material-netlify/)

- [Fly.io](https://documentation.breadnet.co.uk/cloud/fly/mkdocs-on-fly/#prerequisites)

- [Scaleway](https://www.scaleway.com/en/docs/tutorials/using-bucket-website-with-mkdocs/)

---

### User Recipes How To Write Recipes (`docs/user/recipes/how-to-write-recipes.md`)

# How to Write Recipes

This is an example of how to structure a Recipe. The first paragraph or two should explain the purpose of the recipe succinctly, including why it's useful, if that's not obvious.

Recipes are intended to document:

- How to use Foam's basic features
- Power user pro-tips
- Useful customisations of the default Foam environment
- Integrations with third party tools and extensions (should be listed below)

## Required Extensions

- **[Hacker Typer](https://marketplace.visualstudio.com/items?itemName=jevakallio.vscode-hacker-typer)** (not really required for this recipe, just an example)
- [Foam for VSCode](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) (installed by default)

The first section should be a bulleted list of extensions required to use this recipe. At a minimum, this section should list all additional, non-standard extensions.

Ideally, you should also note which Foam [[recommended-extensions]] are responsible for providing this feature, so any issue reports can be directed to the correct repositories.

When creating new recipes, if you don't know which extension does what, you can leave it out.

## Instructions

Here we describe how the extension should be used.



You may include a screenshot or GIF of the feature in action by uploading an image to the `assets/images` directory. Please try to keep GIFs as small as possible by recording them with a low frame rate.

That's pretty much it!

## How to contribute

You can add [[recipes]] by creating a pull request to [foambubble/foam](https://github.com/foambubble/foam) on GitHub.

Read more in our [contribution guide](https://github.com/foambubble/foam/blob/main/CONTRIBUTING.md).

[recommended-extensions]: ../getting-started/recommended-extensions.md 'Recommended Extensions'
[recipes]: recipes.md 'Recipes'

---

### User Recipes Markup Converter (`docs/user/recipes/markup-converter.md`)

# Markup Converter

This #recipe allows you to convert any document into Markdown for storing them in your notes.

We will be using [Pandoc](https://pandoc.org/), a popular universal document converter. It can convert documents in Microsoft Word, HTML, LaTeX, and many other formats to various formats including markdown and many others.

## Instructions

We will go through the example of converting Microsoft Word documents to Markdown. For detailed instructions on how to use Pandoc, please refer to the [Pandoc documentation](https://pandoc.org/MANUAL.html).

1. [Install Pandoc](https://pandoc.org/installing.html)
1. Open the terminal of your choice and verify that Pandoc is installed by running `pandoc --version`
1. Copy the Microsoft Word documents that you want to convert into a new folder
1. Change the current directory to the folder containing the Microsoft Word documents
1. Copy one of the following commands (based on your operating system) into your terminal and press `Enter` to run

### Linux and macOS (Bash)

```bash
find -name "*.docx" -type f -exec sh -c '
      for f; do
         pandoc --extract-media=./ -f docx -t markdown -o "${f%.*}.md" "$f"
      done
   ' find-sh {} +
```

### Windows (PowerShell)

```powershell
Get-ChildItem . -Filter *.docx |
Foreach-Object {
    pandoc --extract-media=./ --from docx --to markdown $_ -o $_.Name.Replace('.docx', '.md')
}
```

### Relevant Configurations

[Pandoc](https://pandoc.org/) accepts a range of command line arguments to control the conversion process. Here, we'll mention a few that are relevant to the example above.

- `--extract-media=./` is used to extract the images from the Microsoft Word documents and store them in a subfolder named `media`
- `-t markdown` converts the Microsoft Word documents to [Pandoc’s Markdown](https://pandoc.org/MANUAL.html#pandocs-markdown). You can also use `-t gfm` to convert to [GitHub Flavored Markdown](https://docs.github.com/en/get-started/writing-on-github)

Note that you may want to review the converted Markdown files to ensure that the conversion was successful. Then, You may want to delete the original Microsoft Word documents.

---

### User Recipes Migrating From Obsidian (`docs/user/recipes/migrating-from-obsidian.md`)

# Coming from Obsidian

Good news: an Obsidian vault is, for the most part, already a Foam workspace. Both store your notes as plain Markdown files in a directory, so in most cases you can just open your vault folder in VS Code with the Foam extension installed and start working.

## Try it in 30 seconds

1. Install the [Foam extension](https://marketplace.visualstudio.com/items?itemName=foam.foam-vscode) in VS Code.
2. **File → Open Folder…** and pick your existing Obsidian vault.
3. That's it — wikilinks, backlinks, the graph, and tags should all work.

You can keep using Obsidian on the same folder side-by-side. Foam doesn't change your files unless you ask it to.

## What works the same

| Obsidian              | Foam                |
| --------------------- | ------------------- |
| `[[wikilinks]]`       | [[wikilinks]]       |
| `![[embeds]]`         | [[embeds]]          |
| `[[note#^block-id]]`  | [[block-anchors]]   |
| Backlinks panel       | [[backlinking]]     |
| Graph view            | [[graph-view]]      |
| Daily notes           | [[daily-notes]]     |
| Templates             | [[templates]]       |
| Tags (`#tag`)         | [[tags]]            |
| Frontmatter / aliases | [[note-properties]] |

## What's different or missing

These are the things most likely to surprise you:

- **Live preview / WYSIWYG editing.** Foam uses VS Code's standard split editor + preview pane rather than inline rendering.
- **Community plugins.** Obsidian plugins don't run in Foam. Foam relies on the wider VS Code extension ecosystem instead — see [[recommended-extensions]].
- **Canvas.** Not supported (tracked in [#1450](https://github.com/foambubble/foam/issues/1450)).
- **Tasks plugin syntax.** Not supported (tracked in [#1466](https://github.com/foambubble/foam/issues/1466)).
- **Callouts / Admonitions** (`> [!note]`). Not rendered natively; works as a normal blockquote.
- **Wikilink resolution.** Foam and Obsidian agree on most cases but resolve identifier-style links slightly differently. See the comparison table in [[wikilinks]].

## A few practical tips

- **`.obsidian/` folder.** Leave it alone if you're keeping both tools. Add it to `.gitignore` if you only want to track notes.
- **Templates.** Foam templates live in `.foam/templates/` — see [[templates]] for the format.
- **Don't see something here?** Search [open issues](https://github.com/foambubble/foam/issues) — chances are someone has already asked.

## Related

- [[wikilinks]] — full link syntax reference
- [[first-workspace]] — set up Foam from scratch
- [[recommended-extensions]] — VS Code extensions that pair well with Foam

[wikilinks]: ../features/wikilinks.md 'Wikilinks'
[embeds]: ../features/embeds.md 'Note Embeds'
[block-anchors]: ../features/block-anchors.md 'Block Anchors'
[backlinking]: ../features/backlinking.md 'Backlinking'
[graph-view]: ../features/graph-view.md 'Graph Visualization'
[daily-notes]: ../features/daily-notes.md 'Daily Notes'
[templates]: ../features/templates.md 'Note Templates'
[tags]: ../features/tags.md 'Tags'
[note-properties]: ../features/note-properties.md 'Note Properties'
[recommended-extensions]: ../getting-started/recommended-extensions.md 'Recommended Extensions'
[first-workspace]: ../getting-started/first-workspace.md 'Creating Your First Workspace'

---

### User Recipes Migrating From Onenote (`docs/user/recipes/migrating-from-onenote.md`)

# Migrating from OneNote

This guide mostly duplicates the instructions at the repo for the PowerShell [script](https://github.com/nixsee/ConvertOneNote2MarkDown).

## Summary

The powershell script 'ConvertOneNote2MarkDown-v2.ps1' will utilize the OneNote Object Model on your workstation to convert all OneNote pages to Word documents and then utilizes PanDoc to convert the Word documents to Markdown (.md) format. It will also:

- Create a folder structure for your Notebooks and Sections.
- Process pages that are in sections at the Notebook, Section Group and 1st Nested Section Group levels.
- Allow you you choose between putting all Images in a central '/media' folder for each notebook, or in a separate '/media' folder in each folder of the hierarchy.
- Fix image references in the resulting .md files, generating relative references to the image files within the markdown document.
- A title, description, and date header will be added to each file as well.
- And more (see details at repo)!

## Usage

1.  Start the OneNote application. All notebooks currently loaded in [OneNote](https://getonetastic.com/download) will be converted.
2.  It is advised that you install [Onetastic](https://getonetastic.com/download) and the attached macro, which will automatically expand any collapsed paragraphs in the notebook. They won't be exported otherwise.
    - To install the macro, click the New Macro Button within the Onetastic Toolbar and then select File -> Import and select the .xml macro included in the release.
    - Run the macro for each Notebook that is open
3.  For the next sections, it is highly recommended that you use VS Code, and its embedded PowerShell terminal, as this allows you to edit and run the script, as well as check the results of the .md output all in one window.
4.  Whatever you choose, you will need to do the following:
    1. Clone the script to your computer (see [here](https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository), if you're unfamiliar with git).
    2. Once cloned, navigate to the repo folder. In VS Code, use File -> Add Folder to Workspace, right click on the folder in the left side bar and click [Open In Integrated Terminal](../../assets/images/migrating-one-note.png).
    3. Run the script by executing
       `.\ConvertOnenote2Markdown-v2`


        * if you receive an error, try running this line to bypass security:
         ```Set-ExecutionPolicy Bypass -Scope Process```
        * if you still have trouble, try running both Onenote and Powershell as an administrator.
5.  It will ask you for the path to store the markdown folder structure. Please use an empty folder. If using VS Code, you might not be able to paste the filepath - right click on the blinking cursor and it will paste from clipboard. **Attention:** use a full absolute path for the destination.
6.  Read the prompts carefully to select your desired options. If you aren't actively editing your pages in Onenote, it is HIGHLY recommended that you don't delete the intermediate word docs, as they take 80+% of the time to generate. They are stored in their own folder, out of the way. You can then quickly re-run the script with different parameters until you find what you like.
7.  Sit back and wait until the process completes.
8.  To stop the process at any time, press Ctrl+C.
9.  If you like, you can inspect some of the .md files prior to completion. If you're not happy with the results, stop the process, delete the .md and re-run with different parameters.
10. At this point, you should be ready to load the new directory into Foam!

---

### User Recipes Multi Root Workspaces (`docs/user/recipes/multi-root-workspaces.md`)

# Multi-root workspaces

A VS Code [multi-root workspace](https://code.visualstudio.com/docs/editor/multi-root-workspaces) has several folders side by side. A common setup is a knowledge base you add to each of your projects, so both your own notes and the project's notes are at hand:

```
my-project.code-workspace
├── my-project/       ← first folder
└── knowledge-base/   ← your knowledge base, added to every workspace
```

Foam indexes every folder, so links and the graph work across them. What needs care is where new notes go: by default, Foam creates them in the first folder.

## Settings

Put Foam settings in the `.code-workspace` file or in your user settings. In a multi-root workspace, VS Code ignores them in a folder's own `.vscode/settings.json`.

## Templates

Foam looks for [[templates]] in the templates folder (`.foam/templates` by default) of every folder in the workspace:

- **Foam: Create New Note From Template** lists the templates of all folders. When two folders have a template with the same name, it shows which folder each one is in.
- For the special `new-note` and `daily-note` templates, Foam checks each folder in the order they're listed and uses the first one it finds.
- New templates are created in the first folder.

## Create notes in a specific folder

A template's `filepath` can name the folder a note goes in: start it with `/` and the folder's name. For example, if you want all new notes to go in `knowledge-base/inbox/`, your `new-note` template, `knowledge-base/.foam/templates/new-note.md`, would look like this:

```markdown
---
foam_template:
  filepath: '/knowledge-base/inbox/$FOAM_SLUG.md'
---

# $FOAM_TITLE
```

**Foam: Create New Note**, and Ctrl+clicking a `[[placeholder]]`, then create the note in `knowledge-base/inbox/`, in every workspace you add `knowledge-base` to, as long as the project has no `new-note` template of its own. To choose for each note instead, give the template another name, such as `global-note.md`, and pick it with **Foam: Create New Note From Template**.

[[daily-notes]] work the same way, with `knowledge-base/.foam/templates/daily-note.md`:

```markdown
---
foam_template:
  filepath: '/knowledge-base/journal/$FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE.md'
---

# $FOAM_DATE_YEAR-$FOAM_DATE_MONTH-$FOAM_DATE_DATE
```

A few things to know:

- Use the folder's name on disk, with the same capitalization, not a different name you gave it in the `.code-workspace` file.
- If no folder has that name, the path starts from the first folder: `/journal/today.md` goes in `my-project/journal/`.
- The same template works when you open the knowledge base on its own: `/knowledge-base/inbox/` is then its own `inbox/` folder.

With the default settings, notes created without a `filepath`, such as with **Foam: Create New Note** when there's no `new-note` template, go in the first folder.

## Related

- [[templates]] — the full template reference
- [[daily-notes]] — daily note templates
- [[notes-in-a-subfolder]] — notes inside a bigger project, in a single folder

[templates]: ../features/templates.md 'Note Templates'
[daily-notes]: ../features/daily-notes.md 'Daily Notes'
[notes-in-a-subfolder]: notes-in-a-subfolder.md 'Keep your notes in a subfolder'

---

### User Recipes Notes In A Subfolder (`docs/user/recipes/notes-in-a-subfolder.md`)

# Keep your notes in a subfolder

Sometimes your notes live inside a bigger project rather than in a repository of their own — a `knowledge-base` folder next to your source code, say:

```
my-project/
├── knowledge-base/     ← your notes
├── src/
└── README.md
```

Foam works in this layout with three bits of configuration. There's no single "Foam root" setting: instead you tell Foam which files to index, where your templates live, and where new notes should go.

## 1. Index only your notes

In `.vscode/settings.json`:

```json
{
  "foam.files.include": ["knowledge-base/**"]
}
```

Foam now builds the graph from your notes alone and ignores the rest of the project. Reload the window to apply it.

## 2. Point at your templates

```json
{
  "foam.files.include": ["knowledge-base/**"],
  "foam.templates.folder": "knowledge-base/.foam/templates"
}
```

Your [[templates]] live at `knowledge-base/.foam/templates/` rather than the project root.

## 3. Create new notes in the right place

By default, clicking a `[[new-note]]` placeholder creates the file at the top of the project. To send it to your notes folder instead, create `knowledge-base/.foam/templates/new-note.md`:

```markdown
---
foam_template:
  filepath: 'knowledge-base/${FOAM_TITLE}.md'
---

# ${FOAM_TITLE}
```

Foam uses `new-note.md` whenever it creates a note without being told where to put it, so this covers Ctrl+clicking a placeholder as well as the **Foam: Create New Note** command.

For [[daily-notes]], do the same in `knowledge-base/.foam/templates/daily-note.md`:

```markdown
---
foam_template:
  filepath: 'knowledge-base/journal/${FOAM_DATE_YEAR}-${FOAM_DATE_MONTH}-${FOAM_DATE_DATE}.md'
---

# ${FOAM_DATE_YEAR}-${FOAM_DATE_MONTH}-${FOAM_DATE_DATE}
```

## Linking

`[[wikilinks]]` work exactly as they do anywhere else — `[[my-note]]` finds `knowledge-base/my-note.md`, because Foam only indexes your notes folder.

The one thing to know is that a leading slash means "the folder you opened in VS Code", not "my notes folder". So `[[/my-note]]` and `[my note](/my-note.md)` point at `my-project/my-note.md`, which isn't where your notes are. Write `[[/knowledge-base/my-note]]` if you want the full path — or just use `[[my-note]]`, which is shorter and unambiguous.

This also means you can link out to the rest of the project: `[the build script](/scripts/build.sh)` does what you'd expect, and works on GitHub too.

## What stays at the project root

When you delete a note, Foam moves it to `.foam/trash/` at the top of the project, and [[smart-folders]] are saved under `.foam/queries/`. If you'd rather keep everything together, move those folders into your notes directory by hand — Foam will recreate them at the project root next time, so it's a matter of taste rather than correctness.

## Related

- [[first-workspace]] — setting up a Foam workspace
- [[templates]] — the full template reference
- [[wikilinks]] — link syntax, including paths and identifiers

[templates]: ../features/templates.md 'Note Templates'
[daily-notes]: ../features/daily-notes.md 'Daily Notes'
[wikilinks]: ../features/wikilinks.md 'Wikilinks'
[smart-folders]: ../features/smart-folders.md 'Smart Folders'
[first-workspace]: ../getting-started/first-workspace.md 'Creating Your First Workspace'

---

### User Recipes Predefined User Snippets (`docs/user/recipes/predefined-user-snippets.md`)

# Pre-defined User Snippets

This #recipe allows us to introduce slash-style commands to Foam, by using [VS Code Snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets). Consider the below snippets:

```json
{
  "Zettelkasten Id": {
    "scope": "markdown",
    "prefix": "/id",
    "description": "Zettelkasten Id",
    "body": [
      "${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}"
    ]
  },
  "Current date": {
    "scope": "markdown",
    "prefix": "/date",
    "description": "Current date",
    "body": [
      "${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE} ${CURRENT_HOUR}:${CURRENT_MINUTE}:${CURRENT_SECOND}"
    ]
  }
}
```

Which would look like:


Using snippets enables Foam users to add [[custom-snippets]] themselves so they live alongside the first-class `/commands`.

## Notes & Considerations

- VS Code supplies "commands" already via the command palette
  - Consider the UX around this. Users less familiar with VS Code are more likely to be familiar with `/` to trigger a command menu. Experienced VS Code users may be more likely to favour the command palette.
- We can use `TabCompletionProvider` and `snippets` and mix them (maybe) via the following VS Code setting: `"editor.snippetSuggestions": "inline" | "top" | "bottom" | "none"`
- For more discussion, consult the PR [here](https://github.com/foambubble/foam/pull/192).

## Simplifying Markdown Syntax

Some markdown syntax is difficult for users who have never authored markdown before. Take for example a checkbox/todo. The following syntax is required:

```
- [ ] Something todo...
```

We could provide snippets that expand out into the associated markdown syntax, like in the below GIF:


The JSON for these snippets can be found [here](https://github.com/foambubble/foam/pull/192#issuecomment-666736270).

[custom-snippets]: ../features/custom-snippets.md 'Adding Custom Snippets'

---

### User Recipes Real Time Collaboration (`docs/user/recipes/real-time-collaboration.md`)

# Real-time Collaboration

This #recipe is here to just tell you that VS Code Live Share will allow you to collaborate live on your notes.

---

### User Recipes Recipes (`docs/user/recipes/recipes.md`)

# Recipes

A #recipe is a guide, tip or strategy for getting the most out of your Foam workspace!

- [Recipes](#recipes)
  - [Contribute](#contribute)
  - [Take smart notes](#take-smart-notes)
  - [Discover](#discover)
  - [Organise](#organise)
  - [Write](#write)
  - [Version control](#version-control)
  - [Publish](#publish)
  - [Collaborate](#collaborate)
  - [Workflow](#workflow)
  - [Creative ideas](#creative-ideas)
  - [Other](#other)

## Contribute

- Start by reading the [contribution guide](https://github.com/foambubble/foam/blob/main/CONTRIBUTING.md)
- If you discover features not listed here, we'd love to have them! [[how-to-write-recipes]].

## Take smart notes

- Clip webpages with [[web-clipper]]
- Convert Microsoft Word files into Markdown with [[markup-converter]]
- Coming from Obsidian? See [[migrating-from-obsidian]]
- Coming from OneNote? See [[migrating-from-onenote]]

## Discover

- [[search-and-navigate-notes]]
- Explore your notes using [[graph-view]]
- Discover relationships with [[backlinking]]

## Organise

- Using [[backlinking]] for reference lists.
- Keeping your notes inside a bigger project with [[notes-in-a-subfolder]].
- Using one notes folder across several projects with [[multi-root-workspaces]].

## Write

- Link documents with [[wikilinks]].
- Create notes with custom [[commands]] and key bindings
- Instantly create and access your [[daily-notes]]
- Add and explore [[tags]]
- Create [[templates]]
- Find [[orphans]]
- Draw [[diagrams-in-markdown]]
- Prettify your links, [[automatically-expand-urls-to-well-titled-links]]
- Style your environment with [[custom-markdown-preview-styles]]
- Paste and link [[add-images-to-notes]]
- [[shows-image-preview-on-hover]]
- [Markdown All-in-One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one) features
  - Manage checklists
  - Automatic Table of Contents
  - Live preview markdown
  - _More..._
- VS Code Advanced Features
  - Focus with Zen Mode
- Display content of other notes in the preview tab by [[embeds]]

## Version control

- Quick commits with VS Code's built-in source control
- Store your workspace in an auto-synced GitHub repo with [[write-your-notes-in-github-gist]]
- Sync your GitHub repo automatically using the [GitDoc VSCode Plugin](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.gitdoc) [[automatic-git-syncing]].

## Publish

- Publish using official Foam template
  - Publish to [[publish-to-github-pages]]
  - Publish to [[publish-to-gitlab-pages]]
  - Publish to [[publish-to-azure-devops-wiki]]
  - Publish to [[publish-to-vercel]]
- Publish using community templates
  - [[publish-to-netlify-with-eleventy]] by [@juanfrank77](https://github.com/juanfrank77)
  - [[generate-gatsby-site]] by [@mathieudutour](https://github.com/mathieudutour) and [@hikerpig](https://github.com/hikerpig)
  - [[generate-material-for-mkdocs-site]] by [@djplaner](https://github.com/djplaner)
- Make the site your own by [[publish-to-github]].
- Render math symbols, by either
  - adding client-side [[math-support-with-mathjax]] to the default [[publish-to-github-pages]] site
  - adding a custom Jekyll plugin to support [[math-support-with-katex]]
- Export note to PDF [[export-to-pdf]]

## Collaborate

- Give your team push access to your [GitHub repo](https://docs.github.com/en/account-and-profile/setting-up-and-managing-your-personal-account-on-github/managing-access-to-your-personal-repositories/inviting-collaborators-to-a-personal-repository)
- Real-time collaboration via VS Code Live Share [[real-time-collaboration]]
- Accept patches via GitHub PRs

## Workflow

- Capture notes from Drafts app on iOS [[capture-notes-with-drafts-pro]]
- Capture notes from iOS Shortcuts [[capture-notes-with-shortcuts-and-github-actions]]

## Creative ideas

Creative ideas welcome!

- Support [Anki](https://apps.ankiweb.net/) cards from notes like [Remnote](https://www.remnote.io/)

_See [[how-to-write-recipes]] and the [contribution guide](https://github.com/foambubble/foam/blob/main/CONTRIBUTING.md)._

## Other

Thought of a recipe but don't see a category for them? Add them here and we'll organise them once we detect a theme.

_See [[how-to-write-recipes]] and the [contribution guide](https://github.com/foambubble/foam/blob/main/CONTRIBUTING.md)._

[how-to-write-recipes]: how-to-write-recipes.md 'How to Write Recipes'
[search-and-navigate-notes]: search-and-navigate-notes.md 'Search and Navigate Notes'
[web-clipper]: web-clipper.md 'Web Clipper'
[markup-converter]: markup-converter.md 'Markup Converter'
[migrating-from-obsidian]: migrating-from-obsidian.md 'Coming from Obsidian'
[migrating-from-onenote]: migrating-from-onenote.md 'Migrating from OneNote'
[backlinking]: ../features/backlinking.md 'Backlinking'
[wikilinks]: ../features/wikilinks.md 'Wikilinks'
[commands]: ../features/commands.md 'Foam Commands'
[daily-notes]: ../features/daily-notes.md 'Daily Notes'
[tags]: ../features/tags.md 'Tags'
[orphans]: ../tools/orphans.md 'Orphaned Notes'
[diagrams-in-markdown]: diagrams-in-markdown.md 'Diagrams in Markdown'
[automatically-expand-urls-to-well-titled-links]: automatically-expand-urls-to-well-titled-links.md 'Automatically Expand URLs to Well-Titled Links'
[custom-markdown-preview-styles]: ../features/custom-markdown-preview-styles.md 'Custom Markdown Preview Styles'
[add-images-to-notes]: add-images-to-notes.md 'Add images to your notes'
[shows-image-preview-on-hover]: shows-image-preview-on-hover.md 'Shows Image Preview on Hover'
[write-your-notes-in-github-gist]: write-your-notes-in-github-gist.md 'Write your notes in GitHub Gist'
[automatic-git-syncing]: automatic-git-syncing.md 'Automatically Sync with Git'
[publish-to-github-pages]: ../publishing/publish-to-github-pages.md 'GitHub Pages'
[publish-to-gitlab-pages]: ../publishing/publish-to-gitlab-pages.md 'GitLab Pages'
[publish-to-azure-devops-wiki]: ../publishing/publish-to-azure-devops-wiki.md 'Publish to Azure DevOps Wiki'
[publish-to-vercel]: ../publishing/publish-to-vercel.md 'Publish to Vercel'
[publish-to-netlify-with-eleventy]: ../publishing/publish-to-netlify-with-eleventy.md 'Publish to Netlify with Eleventy'
[generate-gatsby-site]: ../publishing/generate-gatsby-site.md 'Generate a site using Gatsby'
[generate-material-for-mkdocs-site]: generate-material-for-mkdocs-site.md 'Generate a site using the Material for MkDocs theme'
[publish-to-github]: ../publishing/publish-to-github.md 'Publish to GitHub'
[math-support-with-mathjax]: ../publishing/math-support-with-mathjax.md 'Math Support'
[math-support-with-katex]: ../publishing/math-support-with-katex.md 'Katex Math Rendering'
[export-to-pdf]: export-to-pdf.md 'Export to PDF'
[real-time-collaboration]: real-time-collaboration.md 'Real-time Collaboration'
[capture-notes-with-drafts-pro]: capture-notes-with-drafts-pro.md 'Capture Notes With Drafts Pro'
[capture-notes-with-shortcuts-and-github-actions]: capture-notes-with-shortcuts-and-github-actions.md 'Capture Notes With Shortcuts and GitHub Actions'
[graph-view]: ../features/graph-view.md 'Graph Visualization'
[templates]: ../features/templates.md 'Note Templates'
[embeds]: ../features/embeds.md 'Note Embeds'
[notes-in-a-subfolder]: notes-in-a-subfolder.md 'Keep your notes in a subfolder'
[multi-root-workspaces]: multi-root-workspaces.md 'Multi-root workspaces'

---

### User Recipes Search And Navigate Notes (`docs/user/recipes/search-and-navigate-notes.md`)

# Search and Navigate Notes

This #recipe covers the ways you can find and navigate notes in Foam.

## Quick Open

Press `Cmd+P` (`Ctrl+P` on Windows) and type a note name to open it directly. Partial matches work — `proj meet` will find `projects/meeting-notes.md`.

## Full-text Search

Press `Cmd+Shift+F` (`Ctrl+Shift+F` on Windows) to search across all note content. Use the filter icon to restrict search to specific folders or file types.

## Note Navigator Panel

The **Note Navigator** panel in the sidebar lets you browse and filter all notes in your workspace. Use the filter input to narrow by name, and switch between flat and grouped-by-folder views from the panel toolbar.

## Other Panels

Foam adds several panels to the sidebar that help you discover notes:

- **Backlinks** — shows which notes link to the currently open note
- **Placeholders** — lists wikilinks that don't yet have a corresponding file
- **Orphans** — lists notes with no incoming or outgoing links (see [[orphans]])
- **Tags** — browse all tags and jump to tagged notes (see [[tags]])

## Graph View

The [[graph-view]] gives a visual overview of your entire knowledge base. Click any node to open that note. You can also [[resource-filters|filter the graph]] to focus on a subset of notes by tag, type, path, or title.

## Random Note

Run **"Foam: Open Random Note"** from the command palette to resurface forgotten notes.

[orphans]: ../tools/orphans.md 'Orphaned Notes'
[tags]: ../features/tags.md 'Tags'
[graph-view]: ../features/graph-view.md 'Graph View'
[resource-filters]: ../features/resource-filters.md 'Resource Filters'

---

### User Recipes Shows Image Preview On Hover (`docs/user/recipes/shows-image-preview-on-hover.md`)

# Shows Image Preview on Hover

This #recipe allows you to see a preview of an image on hover.

Use extension: [Image preview](https://marketplace.visualstudio.com/items?itemName=kisstkondoros.vscode-gutter-preview) to shows image preview in the gutter and on hover

It looks like this

---

### User Recipes Take Notes From Mobile Phone (`docs/user/recipes/take-notes-from-mobile-phone.md`)

# Take notes on mobile phones

This #recipe offers solutions to taking Foam notes on the go.

For the time being we have decided to not build a mobile app, but rely on third parties.

The most promising options are:

### [GitJournal](https://gitjournal.io/)

Pros

- Open source
- Already a usable solution.
- Provides functionality to edit, create, and browser markdown files.
- Support journal mode, todo lists, and free writing
- Syncs to GitHub repo
- Supports Wikilinks
- Supports Backlinks
- Developer is happy to prioritize Foam compatibility

Cons

- Doesn't generate link reference lists (but this is ok, since [[workspace-lint]] as a GitHub action can solve this)
- Not as sleek as Apple/Google notes, some keyboard state glitching on Android, etc.
- Lack of control over roadmap. Established product with a paid plan, so may not be open to Foam-supportive changes and additions that don't benefit most users.

Verdict: Good. By far best effort/outcome ratio would be to help improve GitJournal rather than building a [bespoke mobile app](#bespoke-mobile-app-for-foam).

### GitHub Codespaces

Pros

- Works out of the box just like the desktop app

Cons

- not generally available quite yet
- [Pricing](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/about-billing-for-codespaces)

For a quick demo, see <https://www.youtube.com/watch?v=KI5m4Uy8_4I>.

Verdict: Good. Pricing should be reasonable for taking notes on the fly. Harder to assess for people who would constantly use Foam from mobile phone.

## Bespoke mobile app for Foam

Given we already have a solution, why would we spend time and effort building a bespoke mobile app?

- Taking notes on the go is a key part of a good note taking process, and the process should feel effortless
- Having a custom app could help us support key user workflows in a more Foam-specific manner

If such an app was worth building, it would have to have the following features:

- Instant loading and syncing for quick notes
- Sleek, simple, beautifully designed user experience.
- Ability to search and navigate forward links and back links (only in paid GitJournal version)
- Killer feature that makes it the best note taking tool for Foam (?)

Given the effort vs reward ratio, it's a low priority for core team, but if someone wants to work on this, we can provide support! Talk to us on the #mobile-apps channel on [Foam Discord](https://discord.com/invite/HV2tn2FpEk).

[workspace-lint]: ../tools/workspace-lint.md 'Lint'

---

### User Recipes Web Clipper (`docs/user/recipes/web-clipper.md`)

# Web Clipper

This #recipe allows you to convert any web content into Markdown for storing them in your notes.

There are a couple of options when it comes to clipping web pages:

- [Web Clipper](https://marketplace.visualstudio.com/items?itemName=jsartelle.web-clipper)

  - This is a Web Clipper as a VSCode extension, takes a webpage URL and outputs Markdown. Uses [mercury](https://github.com/postlight/mercury-parser)

- [Markdown Clipper](https://github.com/deathau/markdownload)

  - A Firefox and Google Chrome extension to clip websites and download them into a readable markdown file.

- [Web Clipper](https://clipper.website/)
  - A Firefox, Chrome and Edge extension to clip websites and save them directly to the GitHub repository into a readable markdown file.

---

### User Recipes Write Your Notes In Github Gist (`docs/user/recipes/write-your-notes-in-github-gist.md`)

# Write your notes in GitHub Gist

This #recipe will allow you to persist your notes in a GitHub repository, and automatically sync changes without needing to manually commit/push/pull, then GistPad might be an option worth exploring.

[GistPad](https://aka.ms/gistpad) is a Visual Studio Code extension that allows you to edit your GitHub gists and repos, without needing to clone anything locally.

It provides support for editing Foam workspaces, complete with `[[link]]` [completion/navigation](https://github.com/vsls-contrib/gistpad#links), [daily pages](https://github.com/vsls-contrib/gistpad#daily-pages), [pasting images](https://github.com/vsls-contrib/gistpad#pasting-images-1) and [backlinks](https://github.com/vsls-contrib/gistpad#backlinks).

<img width="700px" src="https://user-images.githubusercontent.com/116461/87234714-96ba9400-c388-11ea-92c3-544d9a3bb633.png" />

## Getting started

To start using GistPad for your Foam-based knowledge base, simply perform the following steps:

1. Download the [GistPad extension](https://aka.ms/gistpad) and then re-start Visual Studio Code

1. Run the `GistPad: Sign In` command and then complete the authentication flow using your GitHub account

1. Run the `GistPad: Open Repository` command and select the `Create repo from template...` or `Create private repo from template...` depending on your preference

1. Select the `Foam-style wiki` template, and then specify a name for your Foam workspace (e.g. `my-foam-notes`, `johns-knowledge-base`)

Your new repo will be created in your GitHub account, and the `Foam` welcome page will be automatically opened. If you already have an existing Foam workspace in GitHub, then when you run step #3 above, simply select or specify the name of the GitHub repository instead.

> Note: If you have any and all feedback on how GistPad can be improved to support your Foam workflow, please don't hesitate to [let us know](https://github.com/vsls-contrib/gistpad)! 👍

<img width="700px" src="https://user-images.githubusercontent.com/116461/87863222-c1b76180-c90d-11ea-87d9-04bee1c58a0d.png" />

## Managing your workspace

Once you've opened/created the Foam repository, it will appear in the `Repositories` view of the `GistPad` tab (the one with the little notebook icon). From this tree view, you can add/edit/delete/rename new pages, upload local files, as well as view the backlinks for each page (they appear as child notes of a page).

<img width="250px" src="https://user-images.githubusercontent.com/116461/87234704-83a7c400-c388-11ea-90a8-2a660bef4dc5.png" />

## Editing your workspace

When you create or open a page, you can edit the markdown content as usual, as well as [paste images](https://github.com/vsls-contrib/gistpad#pasting-images-1), and create [`[[links]]` to other pages](https://github.com/vsls-contrib/gistpad#links). When you type `[[`, you'll receive auto-completion for the existing pages in your workspace, and you can also automatically create new pages by simply creating a link to it.

Since you're using the Visual Studio Code markdown editor, you can benefit from all of the rich language services (e.g. syntax highlighting, header collapsing), as well as the extension ecosystem (e.g. [Emojisense](https://marketplace.visualstudio.com/items?itemName=bierner.emojisense)).

## Navigating your workspace

When editing a file, you can easily navigate `[[links]]` by hovering over them to see a preview of their contents and/or `cmd+clicking` on them in order to jump to the respective page. Furthermore, when you add a link to a page, a [backlink](https://github.com/vsls-contrib/gistpad#backlinks) is automatically added to it.

You can view a page's backlinks using either of the following techniques:

1. Expanding the file's node in the `Repositories` tree, since it's child nodes will represent backlinks. This makes it easy to browse your pages and their backlinks in a single hierarchical view.

1. Opening a file, and then viewing it's backlinks list at the bottom of the editor view. This makes it easy to read a page and then see its backlinks in a contextually rich way.

## Daily Pages

In addition to creating arbitrary pages, you can use GistPad for journaling or capturing [daily notes](https://github.com/vsls-contrib/gistpad#daily-pages). Simply click the calendar icon in the `Repositories` tree, which will open up the page that represents today. If the page doesn't already exist, then it will be created in the workspace before being opened.

<img width="700px" src="https://user-images.githubusercontent.com/116461/87234721-b356cc00-c388-11ea-946a-e7f9c92258a6.png" />

---

### User Tools Cli (`docs/user/tools/cli.md`)

# Foam CLI

The `foam` command line tool lets you work with your Foam workspace from the terminal — search, inspect, and manage notes without opening VS Code.

## Installation

```bash
npm install foam-cli
```

## Usage

```
foam <command> [options]
```

Set the `FOAM_WORKSPACE` environment variable to avoid typing `--workspace` on every command:

```bash
export FOAM_WORKSPACE=/path/to/your/notes
```

All commands accept `--format json` for machine-readable output, useful for scripting.

## Files outside the workspace

Commands only change files inside the workspace. If a path leads outside it, for example through a folder that is a symlink to somewhere else, the command stops with `Cannot write outside the workspace: <path>` instead of writing there. To work with those files, run the command with `--workspace` pointing at the folder they live in.

## Commands

| Command     | Description                                       |
| ----------- | ------------------------------------------------- |
| [[daily]]   | Show or create the daily note for a date          |
| [[grep]]    | Search note content by pattern                    |
| [[links]]   | Show links to and from a note                     |
| [[lint]]    | Check notes for issues                            |
| [[list]]    | List notes, tags, orphans, placeholders, and more |
| [[mcp]]     | Expose the workspace to AI agents via MCP         |
| [[note]]    | Show, create, move, or delete notes               |
| [[outline]] | Show the heading structure of a note              |
| [[rename]]  | Rename notes, tags, sections, or block anchors    |
| [[search]]  | Search notes by title, tag, or frontmatter        |
| [[tag]]     | List, rename, or search tags                      |
| [[update]]  | Check for a newer version of foam-cli             |

[daily]: cli/daily.md 'foam daily'
[grep]: cli/grep.md 'foam grep'
[links]: cli/links.md 'foam links'
[lint]: cli/lint.md 'foam lint'
[list]: cli/list.md 'foam list'
[mcp]: cli/mcp.md 'foam mcp'
[note]: cli/note.md 'foam note'
[outline]: cli/outline.md 'foam outline'
[rename]: cli/rename.md 'foam rename'
[search]: cli/search.md 'foam search'
[tag]: cli/tag.md 'foam tag'
[update]: cli/update.md 'foam update'

---

### User Tools Foam Logging In Vscode (`docs/user/tools/foam-logging-in-vscode.md`)

# Foam logging in VsCode

The Foam extension logs details about what its doing in vscode's `Output` tab.
Generally this is only useful if you're reporting an issue about Foam.

1. To show the tab, click on `View > Output`.
2. In the dropdown on the right of the tab, select `Foam`.



When reporting an issue about Foam, set the log level to `Debug`:

## Change the log level for the session

Execute the command `Foam: Set log level`.

## Change the default logging level

1. Open workspace settings (`cmd+,`, or execute the `Preferences: Open Workspace Settings` command)
2. Look for the entry `Foam > Logging: Level`

---

### User Tools Orphans (`docs/user/tools/orphans.md`)

# Orphaned Notes

Foam helps you to find orphans: notes that have neither forward links nor backlinks.

Orphans can be found in the Orphans panel.

Two settings allows you to control the behaviour of the Orphans panel:

- `foam.orphans.exclude`: list of glob patterns that will be used to exclude directories. For example, a value of `["journal/**/*"]` would exclude your daily notes.
- `foam.orphans.groupBy`: sets the default view mode of the Orphans panel: either groups by folder (by default), or lists all orphans. The view can be toggled on the fly from the panel, but it won't overwrite the setting.

To list orphans from the terminal, see [[list|foam list orphans]].

[list|foam list orphans]: cli/list.md 'foam list'

---

### User Tools Telemetry (`docs/user/tools/telemetry.md`)

# Telemetry

Foam collects anonymous usage data to help understand how Foam is used and to prioritize improvements. This page describes what is sent, what is never sent, and how to opt out.

## What is never collected

This applies to every Foam component:

- Note content, titles, file names, or tag names
- Wikilink targets, search queries, or any text you typed
- Folder paths or any user-defined string
- Free-text configuration values
- Command arguments, CLI flag values, or MCP tool arguments
- Stack traces or error messages (only the error class name is sent)
- Anything that could identify you personally

## What is collected

Every event includes:

- Which component sent it (`vscode`, `cli`, `mcp`)
- The version of that component and of `@foam/core`
- Your OS family — CLI/MCP send `os.platform` (`darwin`, `linux`, `win32`) and Node version; VS Code's library reports OS and version via its own `common.*` properties (see [Common properties](#common-properties))
- An anonymous identifier — CLI and MCP share an installation UUID generated locally on first run. VS Code uses the pseudonymous machine ID provided by Microsoft's `@vscode/extension-telemetry` library (`common.vscodemachineid`); we cannot disable that and we never link it to the CLI/MCP ID.

At a high level:

- **VS Code extension** sends a small set of session events: that Foam loaded, which commands you ran, your enum/boolean settings, and bucketed workspace size (e.g. "201-500 notes"). No file names, paths, or note titles.
- **CLI** sends one event per invocation: which command ran, how long it took (bucketed: `0-10ms`, `11-50ms`, `51-300ms`, `301-1000ms`, `1-5s`, `5-30s`, `30s+`), and bucketed workspace size.
- **MCP** sends one event per tool call the LLM makes: which tool was called, how long it took, and whether it succeeded. Tool arguments and returned content are never sent.

The full event list is at the [bottom of this page](#full-event-list).

## How to opt out

### VS Code extension

Foam respects VS Code's global telemetry setting. Open Settings, search for `telemetry.telemetryLevel`, and set it to `off`.

### CLI

On the first run, the CLI prints a notice describing what is collected and asks you to confirm. The default is **enabled** — pressing Enter accepts it. Your choice is saved in `~/.config/foam/config.json` and not asked again.

If the CLI is run non-interactively (CI, piped input, MCP launched by Claude Desktop / Cursor, etc.), it cannot prompt — it prints a disclosure to stderr and defaults to enabled **for that session only**. No choice is persisted, so the next interactive CLI run will still ask. To make the choice durable in a non-interactive context, set `FOAM_TELEMETRY=0` or `FOAM_TELEMETRY=1` in the environment, or edit `~/.config/foam/config.json` directly.

You can change your choice at any time:

- Set `FOAM_TELEMETRY=0` in your environment, or
- Edit `~/.config/foam/config.json` and set `"telemetry.enabled": false`

### MCP

MCP runs as a child of the CLI (`foam mcp ...`, typically configured in Claude Desktop / Cursor / `mcp.json`). It inherits the CLI's opt-out — set `FOAM_TELEMETRY=0` in the MCP server's environment, or edit `~/.config/foam/config.json`.

## Where the data goes

All events are sent to a single Azure Application Insights resource owned by the Foam project. Connection strings used to send data are not secrets — they only permit writing events, never reading them. Aggregated, anonymized usage data may be shared with the Foam community to inform roadmap discussions. Raw event data is not shared.

## Full event list

### Common properties

The properties below are attached to every event.

| Property           | Components            | Example                    | Description                                                                            |
| ------------------ | --------------------- | -------------------------- | -------------------------------------------------------------------------------------- |
| `foam.component`   | CLI, MCP, VS Code     | `cli`, `mcp`, `vscode`     | Which Foam component emitted the event                                                 |
| `foam.version`     | CLI, MCP, VS Code     | `0.26.0`                   | Version of that component                                                              |
| `foam.coreVersion` | CLI, MCP, VS Code     | `0.4.1`                    | Version of `@foam/core`                                                                |
| `node.version`     | CLI, MCP              | `22.5.0`                   | Node runtime version (CLI/MCP only — VS Code reports it via `common.platformversion`)  |
| `os.platform`      | CLI, MCP              | `darwin`, `linux`, `win32` | Operating system family (CLI/MCP only — VS Code reports it via `common.os`)            |
| `installationId`   | CLI, MCP              | (random UUID)              | Anonymous installation ID shared across CLI and MCP. Sent on the App Insights envelope as the `ai.user.id` tag, not as an event property. Omitted on the `cli.first-run` event. |

VS Code events additionally carry the `common.*` properties added by Microsoft's `@vscode/extension-telemetry` library — these are not controlled by Foam:

| Property                  | Description                                                                                                       |
| ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `common.extname`          | Extension name (`foam.foam-vscode`)                                                                               |
| `common.extversion`       | Extension version                                                                                                 |
| `common.vscodemachineid`  | Pseudonymous machine identifier generated by VS Code. Distinct from Foam's `installationId`; we cannot disable it. |
| `common.vscodesessionid`  | Per-session identifier generated by VS Code                                                                       |
| `common.vscodeversion`    | VS Code version                                                                                                   |
| `common.vscodecommithash` | VS Code commit hash                                                                                               |
| `common.os`               | OS running VS Code                                                                                                |
| `common.platformversion`  | OS/platform version                                                                                               |
| `common.product`          | VS Code host (`desktop`, `github.dev`, `codespaces`, …)                                                           |
| `common.uikind`           | `web` or `desktop`                                                                                                |
| `common.remotename`       | Type of remote connection if any (`ssh`, `wsl`, `dev-container`, or `other`)                                      |
| `common.nodeArch`         | Node architecture (e.g. `arm64`, `x64`, or `web`)                                                                  |

You can disable VS Code's telemetry — and therefore everything Foam sends from VS Code — via the global **`telemetry.telemetryLevel`** setting (`off`). The CLI and MCP opt-out is separate and is described above.

### Bucket scales

- **Duration**: `<10ms`, `<50ms`, `<500ms`, `<5s`, `<30s`, `30s+`
- **Workspace size (note count)**: `0`, `1-10`, `11-50`, `51-200`, `201-500`, `501-1000`, `1001-2000`, `2001-5000`, `5001-10000`, `10000+`

### VS Code events (`vscode.*`)

| Event                         | When it fires                               | Properties                                                                                                                                                                                 |
| ----------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `vscode.session-started`      | Once per extension activation               | none                                                                                                                                                                                       |
| `vscode.session-with-command` | First Foam command in a session             | none                                                                                                                                                                                       |
| `vscode.session-with-note`    | First markdown file opened in a session     | none                                                                                                                                                                                       |
| `vscode.command`              | Every Foam command invocation               | `command` (identifier only — no arguments)                                                                                                                                                 |
| `vscode.config-snapshot`      | Once per session                            | selected enum/boolean settings — e.g. `graph.onStartup`, `completion.linkFormat`, `links.hover.enable`, `graph.viewsConfigured` (count, not names). Free-text settings are never included. |
| `vscode.workspace-stats`      | Once per session                            | `noteCount` and `attachmentCount` (both bucketed), `numTemplates` (count of files in the templates folder), `hasDailyNoteTemplate`                                                          |
| `vscode.error`                | An unhandled error in a Foam feature        | `context` (feature name), `errorType` (error class name only — no message, no stack)                                                                                                       |

### CLI events (`cli.*`)

| Event | When it fires | Properties |
|---|---|---|
| `cli.command-invoked` | Once per CLI invocation that runs a known command, after it completes. Skipped for `--help`, `--version`, `foam config`, and unknown commands (typos) — those never emit telemetry. | `command`, `durationBucket`, `exitCode`. When the command threw an error caught by the dispatcher, also `errorType` (error class name only — no message, no stack) and `errorContext` (where it was caught — `dispatch`). Some commands attach extra properties — e.g. `note create` and `daily --create` attach `template-type` (one of `default`, `daily-note`, `custom`) and `template-format` (`md` / `js`). Both are omitted when no template was applied (e.g. a `note create` that fell back to the minimal `# title` body). `daily` additionally attaches `mode`: `create` when a new daily note was written this invocation, `open` for read-only lookups and for `--create` against a note that already existed (nothing was written). |
| `cli.first-run` | At most twice per installation: once for the strongest consent outcome we've recorded so far. Anonymous — carries no `installationId`, no `os.platform`, no `node.version`. An install that runs headlessly first (e.g. MCP) fires once with `default_on`; if the same install later answers an interactive CLI prompt, a second event fires with `granted` / `declined` (the "upgrade"). Subsequent runs of either kind are deduped via state.json. | `consent`: `granted` / `declined` (from an interactive prompt), or `default_on` (non-interactive first encounter) |

### MCP events (`mcp.*`)

| Event | When it fires | Properties |
|---|---|---|
| `mcp.session-started` | Once per server start | `client` (e.g. `claude-desktop`, `cursor`, omitted if not exposed); `noteCount` and `attachmentCount` (both bucketed); `mode` (`read` or `read-write` — `read-write` is set when the CLI is started with `--allow-writes`; the default is `read`) |
| `mcp.session-with-tool` | First tool call in a session | none |
| `mcp.tool-invoked` | Every tool call (sent unsampled) | `tool` (name only — arguments never recorded), `durationBucket`, `outcome` (`success` / `error`) |
| `mcp.error` | An unhandled error during MCP dispatch. Rare in practice: tool handlers are wrapped to convert throws into structured `isError: true` results, which surface as `outcome: 'error'` on `mcp.tool-invoked`. `mcp.error` is the safety net for anything that escapes that wrapping. | `context`, `tool`, `errorType` |

---

### User Tools Workspace Lint (`docs/user/tools/workspace-lint.md`)

# Lint

To store your personal knowledge graph in markdown files instead of a database, we need some additional tooling to create and maintain relationships with notes.

**Foam Lint** (inspired by Andy Matuschak's [note-link-janitor](https://github.com/andymatuschak/note-link-janitor)) helps you migrate existing notes to Foam, and maintain your Foam's health over time.

Currently, Foam Lint helps you to:

- Ensure your [[link-reference-definitions]] are up to date
- Ensure every document has a well-formatted title (required for Markdown Links, Markdown Notes, and Foam Gatsby Template compatibility)

The link reference definition check only runs when `foam.edit.linkReferenceDefinitions` is set to `withExtensions` or `withoutExtensions` in your workspace settings. It is `off` by default, so if you want Lint to keep definitions up to date — from VS Code, a git hook, or a GitHub action — turn it on first. See [[link-reference-definitions]].

In the future, Foam Lint can help you with

- Lint, format and structure notes
- Rename and move notes around while keeping their references up to date.

## Using Lint from VS Code (Experimental)

Execute the "Foam: Lint Workspace" command from the command palette.



## Using lint from command line

Foam Lint can be installed from [NPM](https://www.npmjs.com/) and executed as a standalone CLI tool:

```sh
> npm install foam-cli
> foam lint --workspace path/to/workspace
```

You can run Foam Lint as a git hook on every commit to ensure your workspace links are up to date. This can be especially helpful if you edit your markdown documents from other apps.

You can also run Foam Lint from a GitHub action to ensure that all changes coming to your workspace are up to date. This can be useful when editing your Foam notes from mobile (i.e. via [GitJournal](https://gitjournal.io)), or your Foam has multiple contributors and you want to ensure that all changes are correctly integrated.

[link-reference-definitions]: ../features/link-reference-definitions.md 'Link Reference Definitions'

---

### User Tools Cli Daily (`docs/user/tools/cli/daily.md`)

# foam daily

Show or create the daily note for a date.

```
foam daily [options]
```

Without `--create`, the command only reports whether the note exists. With `--create`, it writes the note if it doesn't exist yet, using your daily note template if one is configured.

## Options

| Option                | Description                                                                |
| --------------------- | -------------------------------------------------------------------------- |
| `--date <YYYY-MM-DD>` | Date to target (default: today)                                            |
| `--create`            | Create the note if it doesn't exist                                        |
| `--path-only`         | Print only the resolved file path (useful for scripting)                   |
| `--trust`             | Run a JavaScript daily note template (`daily-note.js`)                     |
| `--workspace <dir>`   | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`      | Output format: `text` (default) or `json`                                  |

## Examples

Show today's daily note status:

```bash
foam daily
# journal/2024-01-15.md  [exists]
```

Create today's daily note:

```bash
foam daily --create
```

Get the path to a specific date's note (for scripting):

```bash
foam daily --date 2024-01-10 --path-only
# /home/user/notes/journal/2024-01-10.md
```

Open today's note in your editor:

```bash
$EDITOR $(foam daily --create --path-only)
```

## Daily note path

If your daily note template (`.foam/templates/daily-note.md` or `.foam/templates/daily-note.js`) sets a file path, the note goes there. Otherwise the deprecated `foam.openDailyNote.*` settings in `.vscode/settings.json` decide, and without them notes go to `journal/YYYY-MM-DD.md` — the same place VS Code puts them. The template, when there is one, always provides the content.

The path must stay inside the workspace, even through symlinks: otherwise `foam daily --create` stops with an error telling you to check the template's file path and the `foam.openDailyNote.directory` setting.

See [[templates]] for how to configure daily note templates.

## JavaScript templates

A JavaScript template runs code on your computer, so when your workspace has `.foam/templates/daily-note.js`, `foam daily` stops with an error unless you add `--trust`:

```bash
foam daily --create --trust
```

Only add `--trust` if you wrote the template yourself, or trust whoever did.

[templates]: ../../features/templates.md 'Note Templates'

---

### User Tools Cli Grep (`docs/user/tools/cli/grep.md`)

# foam grep

Search note content by pattern.

```
foam grep <pattern> [options]
```

Searches the text content of all notes in the workspace. The pattern is matched case-insensitively as a regular expression. Unlike [[search|foam search]], this command searches the full text of each note rather than indexed metadata.

## Options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--context <n>`     | Show `n` lines of surrounding context around each match                    |
| `--no-line-number`  | Omit line numbers from output                                              |
| `--limit <n>`       | Max number of matching files to return (default: 20)                       |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`    | Output format: `text` (default) or `json`                                  |

## Examples

Search for a word across all notes:

```bash
foam grep "quantum"
# physics/quantum-mechanics.md:3: Quantum mechanics describes...
# research/reading-list.md:12: See also quantum entanglement
```

Search with context lines:

```bash
foam grep "TODO" --context 2
```

Limit results:

```bash
foam grep "meeting" --limit 5
```

Use in a script (JSON output):

```bash
foam grep "action item" --format json
```

[search]: search.md 'foam search'

---

### User Tools Cli Links (`docs/user/tools/cli/links.md`)

# foam links

Show links to and from a note.

```
foam links (<identifier> | --path <path>) [options]
```

Displays the outgoing links (notes this note links to) and incoming links (notes that link to this note, also called backlinks). The command can also be invoked as `foam connections`.

## Options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--path <path>`     | Target note by exact file path instead of identifier                       |
| `--outgoing`        | Show only outgoing links                                                   |
| `--incoming`        | Show only incoming links (backlinks)                                       |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`    | Output format: `text` (default) or `json`                                  |

By default, both outgoing and incoming links are shown.

## Examples

Show all links for a note:

```bash
foam links my-note
# Outgoing (2):
#   → related-topic    notes/related-topic.md
#   → another-note     notes/another-note.md
#
# Incoming (1):
#   ← index            index.md
```

Show only backlinks:

```bash
foam links my-note --incoming
```

Target by file path:

```bash
foam links --path notes/my-note.md
```

Get links as JSON for scripting:

```bash
foam links my-note --format json
```

## Note identifiers

Foam identifies notes by the shortest unique part of their filename (without extension). For example, a note at `projects/alpha/notes.md` might be identified as `notes` if that's unique, or `alpha/notes` if there's ambiguity. Use [[note|foam note id]] to check how a note is identified.

See also [[backlinking]] for the backlinks panel in VS Code.

[backlinking]: ../../features/backlinking.md 'Backlinks'
[note]: note.md 'foam note'

---

### User Tools Cli Lint (`docs/user/tools/cli/lint.md`)

# foam lint

Check notes for issues.

```
foam lint [options]
```

Scans all notes in the workspace and reports problems such as missing headings or stale link reference definitions. With `--fix`, auto-fixable issues are corrected in place.

Which rules run depends on your workspace settings — see [Rules](#rules).

Exits with code `2` when issues are found (and no `--fix`), making it easy to use in CI pipelines.

## Options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--fix`             | Apply all auto-fixable issues                                              |
| `--rule <id>`       | Run only the given rule (can be repeated)                                  |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`    | Output format: `text` (default) or `json`                                  |

## Rules

| Rule ID             | Description                                            | Auto-fixable |
| ------------------- | ------------------------------------------------------ | :----------: |
| `missing-heading`   | Notes without a top-level heading                      |     Yes      |
| `stale-definitions` | Link reference definitions that are outdated or unused |     Yes      |

`stale-definitions` only runs when [[link-reference-definitions]] are enabled for the workspace, the same as the "Foam: Lint Workspace" command in VS Code. The `foam.edit.linkReferenceDefinitions` setting is `off` by default, so turn it on in your workspace's `.vscode/settings.json` to have the rule report and fix definitions:

```json
{
  "foam.edit.linkReferenceDefinitions": "withExtensions"
}
```

Asking for the rule with `--rule stale-definitions` while the setting is `off` is a command error (exit `1`).

## Exit codes

| Code | Meaning         |
| ---- | --------------- |
| `0`  | No issues found |
| `1`  | Command error   |
| `2`  | Issues found    |

## Examples

Check the workspace for issues:

```bash
foam lint
# notes/my-note.md
#   5:1  warning  Missing heading  missing-heading
#
# 1 problem (0 errors, 1 warning, 1 fixable with --fix)
```

Fix all auto-fixable issues:

```bash
foam lint --fix
```

Run only one rule:

```bash
foam lint --rule missing-heading
```

Use in CI:

```bash
foam lint || echo "Lint issues found — please fix before merging"
```

Get results as JSON:

```bash
foam lint --format json
```

See also [[workspace-lint]] for running lint from VS Code.

[workspace-lint]: ../workspace-lint.md 'Workspace Lint'
[link-reference-definitions]: ../../features/link-reference-definitions.md 'Link Reference Definitions'

---

### User Tools Cli List (`docs/user/tools/cli/list.md`)

# foam list

List notes, tags, orphans, placeholders, dead-ends, or templates.

```
foam list <what> [options]
```

## What to list

| Value          | Description                                      |
| -------------- | ------------------------------------------------ |
| `notes`        | All notes in the workspace                       |
| `tags`         | All tags used across notes                       |
| `orphans`      | Notes with no links in or out                    |
| `deadends`     | Notes with no outgoing links                     |
| `placeholders` | Wikilinks that don't resolve to an existing note |
| `templates`    | Note templates in `.foam/templates/`             |

## Options

| Option                 | Description                                                                        |
| ---------------------- | ---------------------------------------------------------------------------------- |
| `--type <type>`        | (notes) Filter by resource type: `note` (any markdown file), `attachment`, `image` |
| `--tag <tag>`          | (notes) Filter by tag — repeat for multiple tags (AND logic)                       |
| `--limit <n>`          | (notes, tags) Maximum number of results                                            |
| `--prefix <str>`       | (tags) Filter by tag prefix                                                        |
| `--sort <count\|name>` | (tags) Sort order (default: `name`)                                                |
| `--workspace <dir>`    | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory)         |
| `--format <fmt>`       | Output format: `text` (default) or `json`                                          |

## Examples

List all notes:

```bash
foam list notes
```

List notes with a specific tag:

```bash
foam list notes --tag project
```

List notes tagged both `project` and `active`:

```bash
foam list notes --tag project --tag active
```

List all tags sorted by usage count:

```bash
foam list tags --sort count
```

List tags starting with `project/`:

```bash
foam list tags --prefix project/
```

Find orphaned notes (no links in or out):

```bash
foam list orphans
```

Find broken wikilinks (links that don't resolve to a note):

```bash
foam list placeholders
```

List available templates:

```bash
foam list templates
```

See also [[orphans]] for the orphaned notes panel in VS Code, and [[tags]] for tag management in the editor.

[orphans]: ../orphans.md 'Orphaned Notes'
[tags]: ../../features/tags.md 'Tags'

---

### User Tools Cli Mcp (`docs/user/tools/cli/mcp.md`)

# foam mcp

Run a [Model Context Protocol](https://modelcontextprotocol.io) server over stdio so AI agents (Claude Desktop, Cursor, Zed, …) can read and traverse your Foam workspace as a knowledge graph instead of grepping files.

```
foam mcp [options]
```

The server stays running for the whole agent session: it loads the workspace once at startup and watches the filesystem so subsequent tool calls reflect notes you edited in your editor.

## Options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--allow-writes`    | Let the agent create, edit, delete, and rename notes and tags. Off by default. |

By default the server is **read-only**. Add `--allow-writes` to let the agent modify your notes.

## Connecting an AI client

Most MCP clients accept a JSON configuration similar to this — point them at `foam-cli`:

```json
{
  "mcpServers": {
    "foam": {
      "command": "npx",
      "args": ["foam-cli", "mcp", "--workspace", "/path/to/your/notes"]
    }
  }
}
```

For Claude Desktop the file is `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS and `%APPDATA%\Claude\claude_desktop_config.json` on Windows. Restart the client after editing.

To allow the agent to edit notes too, add `"--allow-writes"` to the `args` array.

## What the agent can do

Read tools (always available):

- Browse the workspace (`list_resources`, `get_resource`, `read_resource`, `get_workspace_info`)
- Follow the link graph (`get_connections`, `traverse_graph`, `get_orphans`, `get_deadends`, `get_placeholders`, `get_graph_summary`)
- Search by tag, frontmatter property, or text (`list_tags`, `search_by_tag`, `search_by_property`, `search_resources`)
- Inspect note structure (`get_outline`)

Write tools (only with `--allow-writes`):

- Create, update, delete, and move notes (`create_resource`, `update_resource`, `delete_resource`, `move_resource`)
- Add, remove, or rename tags (`add_tags`, `remove_tags`, `rename_tag`)

Write tools only change files inside the workspace. A change that would land outside it, including through a symlinked folder, fails with `Cannot write outside the workspace`.

## Logs

Foam writes its logs to stderr (stdout is reserved for MCP traffic). To increase verbosity for troubleshooting:

```bash
FOAM_LOG_LEVEL=debug foam mcp --workspace /path/to/notes
```

Valid values: `debug`, `info`, `warn`, `error` (default).

---

### User Tools Cli Note (`docs/user/tools/cli/note.md`)

# foam note

Show, create, move, or delete notes.

```
foam note <subcommand> [options]
```

## Subcommands

### show

Print metadata for a note.

```bash
foam note show (<identifier> | --path <path>) [--links] [--content]
```

| Option          | Description                                       |
| --------------- | ------------------------------------------------- |
| `--links`       | Include outgoing and incoming links in the output |
| `--content`     | Print the full note content instead of metadata   |
| `--path <path>` | Target by exact file path                         |

Example:

```bash
foam note show my-note
# ID:       my-note
# Title:    My Note
# Path:     notes/my-note.md
# Type:     note
# Tags:     #project #active
```

### id

Print the Foam identifier for a note.

```bash
foam note id (<identifier> | --path <path>)
```

Useful for resolving how Foam identifies a note when there could be ambiguity:

```bash
foam note id my-note
# my-note
```

### create

Create a new note.

```bash
foam note create [options]
```

| Option                 | Description                                  |
| ---------------------- | -------------------------------------------- |
| `--title <title>`      | Note title (default: `untitled`)             |
| `--dir <dir>`          | Directory relative to workspace root         |
| `--property <key=val>` | Add a frontmatter property (can be repeated) |

If a `new-note` template exists in `.foam/templates/`, it is used to generate the note content and file path. See [[templates]] for details.

Example:

```bash
foam note create --title "Meeting Notes" --dir meetings
# Created: meetings/meeting-notes.md  (id: meeting-notes)
```

### move

Move a note to a new path, rewriting all wikilinks that point to it.

```bash
foam note move (<identifier> | --path <path>) --to <new-path>
```

| Option          | Description                                   |
| --------------- | --------------------------------------------- |
| `--to <path>`   | Destination path (relative to workspace root) |
| `--path <path>` | Target by exact file path                     |

Example:

```bash
foam note move my-note --to archive/my-note.md
# Moved: notes/my-note.md → archive/my-note.md  (id: my-note, 3 links updated)
```

### delete

Delete a note.

```bash
foam note delete (<identifier> | --path <path>) [--force] [--permanent]
```

By default, deleted notes are moved to `.foam/trash/` rather than permanently removed. You will be prompted to confirm unless `--force` is passed.

| Option          | Description                                   |
| --------------- | --------------------------------------------- |
| `--force`       | Skip confirmation prompt                      |
| `--permanent`   | Delete permanently instead of moving to trash |
| `--path <path>` | Target by exact file path                     |

Example:

```bash
foam note delete old-draft
# Delete notes/old-draft.md? [y/N] y
# Trashed: notes/old-draft.md → .foam/trash/notes/old-draft.md
```

## Global options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`    | Output format: `text` (default) or `json`                                  |

[templates]: ../../features/templates.md 'Note Templates'

---

### User Tools Cli Outline (`docs/user/tools/cli/outline.md`)

# foam outline

Show the heading structure of a note.

```
foam outline (<identifier> | --path <path>) [options]
```

Prints the headings in a note in order, indented to reflect their level. Useful for getting a quick overview of a long note's structure.

## Options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--path <path>`     | Target note by exact file path instead of identifier                       |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`    | Output format: `text` (default) or `json`                                  |

## Examples

Show the outline of a note:

```bash
foam outline my-note
# Introduction
  ## Background
  ## Goals
# Implementation
  ## Phase 1
  ## Phase 2
# Conclusion
```

Get the outline as JSON (includes line numbers):

```bash
foam outline my-note --format json
```

Target by file path:

```bash
foam outline --path notes/my-note.md
```

---

### User Tools Cli Rename (`docs/user/tools/cli/rename.md`)

# foam rename

Rename notes, tags, sections, or block anchors — with automatic link rewriting.

```
foam rename <subcommand> [options]
```

All subcommands update every wikilink that references the renamed item across the whole workspace.

## Subcommands

### note

Rename a note file and rewrite all wikilinks pointing to it.

```bash
foam rename note (<identifier> | --path <path>) <new-name>
```

| Option                 | Description                            |
| ---------------------- | -------------------------------------- |
| `--target-path <path>` | Move the file to a different directory |
| `--path <path>`        | Target by exact file path              |

Example:

```bash
foam rename note old-name new-name
# Renamed: notes/old-name.md → notes/new-name.md  (id: new-name, 4 links updated)
```

Move to a different directory at the same time:

```bash
foam rename note my-note my-note --target-path archive/
```

### tag

Rename a tag and all its hierarchical children across the workspace.

```bash
foam rename tag <old-tag> <new-tag>
```

| Option    | Description                                                   |
| --------- | ------------------------------------------------------------- |
| `--force` | Skip confirmation if the rename would merge two existing tags |

Example:

```bash
foam rename tag project/active project/in-progress
# Renamed: #project/active → #project/in-progress  (3 notes updated)
```

### section

Rename a heading section in a note and rewrite all `[[note#Section]]` links pointing to it.

```bash
foam rename section (<identifier> | --path <path>) <old-label> <new-label>
```

| Option          | Description               |
| --------------- | ------------------------- |
| `--path <path>` | Target by exact file path |

Example:

```bash
foam rename section my-note "Background" "Context"
# Renamed section "Background" → "Context" in notes/my-note.md  (2 links updated)
```

### block

Rename a block anchor in a note and rewrite all `[[note#^id]]` links pointing to it.

```bash
foam rename block (<identifier> | --path <path>) <old-id> <new-id>
```

| Option          | Description               |
| --------------- | ------------------------- |
| `--path <path>` | Target by exact file path |

Example:

```bash
foam rename block my-note key-insight better-insight
# Renamed block ^key-insight → ^better-insight in notes/my-note.md  (1 link updated)
```

## Global options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`    | Output format: `text` (default) or `json`                                  |

See also [[wikilinks]] for how wikilinks work, and [[block-anchors]] for block anchor syntax.

[wikilinks]: ../../features/wikilinks.md 'Wikilinks'
[block-anchors]: ../../features/block-anchors.md 'Block Anchors'

---

### User Tools Cli Search (`docs/user/tools/cli/search.md`)

# foam search

Search notes by title, alias, tag, or frontmatter property.

```
foam search [<query>] [options]
```

Searches the workspace index. The optional `<query>` is matched against note titles and aliases (substring, case-insensitive). Combine it with `--tag` and `--property` filters to narrow results.

For full-text content search, use [[cli-grep|foam grep]] instead.

## Options

| Option                 | Description                                                                    |
| ---------------------- | ------------------------------------------------------------------------------ |
| `<query>`              | Substring to match against note titles and aliases                             |
| `--tag <tag>`          | Filter by tag (repeat for AND logic)                                           |
| `--property <key=val>` | Filter by frontmatter property; omit `=val` to match any note that has the key |
| `--type <type>`        | Filter by resource type: `note` (any markdown file), `attachment`, `image`     |
| `--limit <n>`          | Maximum number of results (default: 20)                                        |
| `--workspace <dir>`    | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory)     |
| `--format <fmt>`       | Output format: `text` (default) or `json`                                      |

## Examples

Search by title:

```bash
foam search "meeting"
# notes/team-meeting.md:1: # Team Meeting Notes
# notes/one-on-one-meeting.md:1: # One-on-One Meeting
```

Filter by tag:

```bash
foam search --tag project
```

Combine a title query with a tag filter:

```bash
foam search "alpha" --tag active
```

Find all notes with a specific frontmatter property:

```bash
foam search --property status=draft
```

Find all notes that have a `due` property (any value):

```bash
foam search --property due
```

List only daily notes (matches the `type` set in the note's frontmatter):

```bash
foam search --property type=daily-note
```

---

### User Tools Cli Tag (`docs/user/tools/cli/tag.md`)

# foam tag

List, rename, or search tags.

```
foam tag <subcommand> [options]
```

## Subcommands

### list

List all tags in the workspace.

```bash
foam tag list [options]
```

This is an alias for `foam list tags`. Accepts the same filtering and sorting options.

| Option                 | Description                  |
| ---------------------- | ---------------------------- |
| `--prefix <str>`       | Filter by tag prefix         |
| `--sort <count\|name>` | Sort order (default: `name`) |
| `--limit <n>`          | Maximum number of results    |

Example:

```bash
foam tag list
# #daily          (12 notes)
# #project        (8 notes)
# #project/active (3 notes)
```

### rename

Rename a tag across the entire workspace, including its hierarchical children.

```bash
foam tag rename <old> <new>
```

| Option    | Description                                                   |
| --------- | ------------------------------------------------------------- |
| `--force` | Skip confirmation if the rename would merge two existing tags |

Example:

```bash
foam tag rename todo in-progress
# Renamed: #todo → #in-progress  (5 notes updated)
```

Renaming a parent tag also renames its children. Renaming `project` to `work` will also rename `project/active` to `work/active`.

### search

Find all notes with a given tag.

```bash
foam tag search <tag>
```

This is an alias for `foam search --tag <tag>`.

Example:

```bash
foam tag search project
# notes/alpha.md:1: # Project Alpha
# notes/beta.md:1: # Project Beta
```

## Global options

| Option              | Description                                                                |
| ------------------- | -------------------------------------------------------------------------- |
| `--workspace <dir>` | Workspace root (default: `FOAM_WORKSPACE` env var, then current directory) |
| `--format <fmt>`    | Output format: `text` (default) or `json`                                  |

See also [[tags]] for tag management in VS Code.

[tags]: ../../features/tags.md 'Tags'

---

### User Tools Cli Update (`docs/user/tools/cli/update.md`)

# foam update

Check whether a newer version of `foam-cli` is available.

```
foam update
```

The command compares your installed version against the latest release on npm and prints the install command if a newer version exists. It does not install anything for you.

If the npm registry can't be reached, the command falls back to printing the install command without a version comparison.

## Options

| Option   | Description    |
| -------- | -------------- |
| `--help` | Show this help |

## Examples

Check for updates:

```bash
foam update
# Current version: 0.41.0
# Latest version:  0.42.0
#
# To update, run:
#   npm install foam-cli@latest
```

When already up to date:

```bash
foam update
# Current version: 0.42.0
# You are already on the latest version.
```

---

--- METRICS ---
- Files Extracted: 88
- Estimated Token Budget: ~94383 tokens
- Canonical Reference: https://codewiki.google/github.com/foambubble/foam
