packages/foam-cli/README.md
Command-line interface for Foam knowledge bases.
The Foam CLI exposes commands for humans, agents and scripts to interact with a Foam workspace from the terminal — no VS Code required. Targets three audiences:
--format json, pipeable results, non-zero exit codes on failureCommands follow the same foam <command> [args] [options] pattern.
--format json. Default output is concise human-readable text (paths, counts, tables).--flag value syntax: standard Unix-style flags throughout. parameter=value style is not used (that's the Obsidian CLI's convention, suited to their TUI; it doesn't fit a standard CLI).<identifier> resolves via Foam's identifier resolution (same as wikilinks — short name or alias). Use --path <path> for an exact path (relative to workspace root, or absolute). Errors if identifier is ambiguous.0 success, 1 error, 2 lint/check found issues (CI-friendly: foam lint || echo "issues found").# From the foam-cli package directory
cd packages/foam-cli
# Build
yarn build
# Run
node out/index.js <command>
Or set FOAM_WORKSPACE so you don't have to pass --workspace every time:
export FOAM_WORKSPACE=/path/to/your/notes
node out/index.js list notes
For convenience you can create an alias in your shell:
alias foam="node /path/to/foam/packages/foam-cli/out/index.js"
After making changes to the source, re-run yarn build to pick them up.
foam <command> [options]
Global options:
--workspace <dir> Workspace root (default: FOAM_WORKSPACE env var, then cwd)
--format <fmt> Output format: text (default) or json
--help Show help
Run foam <command> --help for command-specific options.
The workspace root is resolved in this order:
--workspace <dir> flagFOAM_WORKSPACE environment variableCommands that operate on a note accept a positional <identifier> (resolved the same way as wikilinks — short name or alias) or --path <path> for an exact path. If an identifier matches more than one note the command exits 1 and lists the candidates.
All commands support --format json. Every JSON response includes id (the Foam short identifier, usable as a wikilink target) alongside uri.
| Code | Meaning |
|---|---|
0 | Success |
1 | Command error |
2 | Issues found (lint/check) |
2 is CI-friendly: foam lint || echo "issues found".
lintCheck workspace notes for issues.
foam lint
foam lint --fix
foam lint --rule missing-heading
foam lint --rule stale-definitions
Rules: missing-heading, stale-definitions. Exit code 2 when issues are found (CI-friendly).
listList notes, tags, orphans, placeholders, dead-ends, or templates.
foam list notes
foam list notes --type daily-note
foam list notes --tag project --tag active
foam list tags
foam list tags --sort count
foam list orphans
foam list deadends
foam list placeholders
foam list templates
noteShow, create, move, or delete a note.
foam note show my-note
foam note show my-note --links # include incoming/outgoing links
foam note show my-note --content # print raw file content
foam note id my-note # print Foam identifier
foam note create --title "My Note"
foam note create --title "My Note" --dir subdir --property status=draft
foam note move my-note --to new-name.md
foam note delete my-note # moves to .foam/trash/ (prompts for confirmation)
foam note delete my-note --force # skip confirmation
foam note delete my-note --permanent # delete permanently
outlineShow the heading structure of a note.
foam outline my-note
foam outline --path path/to/note.md
linksShow links to and from a note. Alias: connections.
foam links my-note
foam links my-note --outgoing
foam links my-note --incoming
dailyShow or create the daily note for a date.
foam daily # today's note
foam daily --date 2025-01-15
foam daily --create # create if it doesn't exist
foam daily --path-only # print resolved path only (for scripting)
tagList, rename, or search tags.
foam tag list
foam tag search project
foam tag rename old-name new-name
foam tag rename old-name new-name --force # skip merge confirmation
grepSearch note content by regex pattern (no workspace graph needed).
foam grep "TODO"
foam grep "TODO" --context 2
foam grep "TODO" --limit 50
foam grep "TODO" --no-line-number
searchSearch notes by title, alias, tag, or frontmatter property.
foam search "meeting notes"
foam search --tag project
foam search --tag project --tag active # AND filter
foam search --property status=draft
foam search --property status # has the property (any value)
foam search --type daily-note
renameRename a note, tag, section, or block anchor — with automatic wikilink rewriting across the workspace.
foam rename note my-note new-name
foam rename note my-note new-name --target-path subdir/
foam rename tag old-tag new-tag
foam rename tag old-tag new-tag --force # allow merging tags
foam rename section my-note "Old Heading" "New Heading"
foam rename block my-note old-anchor new-anchor
publishBuild a static site from your workspace (Astro/Starlight target).
foam publish --out ./site
foam publish /path/to/workspace --out ./site --title "My Notes"
foam publish --out ./site --content-root notes/ --site-url https://example.com