Skip to main content

foamwiki

A Rust-backed, notebook-first Python library and thin CLI for Foam-style Markdown wikis (folders of notes connected by [[wikilinks]]).

The native core reads and parses notes in parallel, maintains the identity and resolution indexes, and stores the link graph. The Python layer preserves the convenient data-oriented API, PyYAML frontmatter values, templates, and filesystem mutation receipts.

Installation

The distribution is named foam-wiki; the Python package and command are both named foamwiki.

Install the stable release:

uv add foam-wiki
# or: python -m pip install foam-wiki

Until the first stable release, opt into the published prerelease:

uv add --prerelease allow foam-wiki
# or: python -m pip install --pre foam-wiki

Run the CLI without adding a project dependency:

uvx --from foam-wiki foamwiki --help

To install the current branch directly from Git:

foam-wiki @ git+https://github.com/nimashoghi/foampy.git

Git installations build the extension from source and require Rust 1.88 or newer. CI produces CPython stable-ABI wheels for manylinux2014 x86_64 and AArch64 (glibc-based Linux), macOS x86_64 and Apple silicon, and Windows x86_64. Each wheel supports Python 3.10 and newer.

Core API

import foamwiki

ws = foamwiki.load()                 # walk up to .foam/ ; parse + index once
note = ws["mean-flow"]             # lookup by shortest id or path
note.title, note.tags, note.outline
note.backlinks()                   # who links here

ws.resolve("flow-matching")        # -> the target Note (falsy Unresolved if broken)
hits = ws.search("TM-align")       # compact immutable Sequence[Hit]
hits[:20]                          # materialize only the rows being inspected
hits.materialize()                 # explicit eager Rows[Hit], when required
foamwiki.orphans(ws)                 # whole-graph census (free functions)
foamwiki.check(ws)                   # strict link diagnostics
foamwiki.rename(ws, note, "papers/meanflow.md")   # dry-run preview; pass dry_run=False to apply

Resolution validates #heading and #^block fragments. Ambiguous attachment suffixes return a falsy Unresolved(reason="ambiguous") rather than silently choosing one file. Percent-encode reserved characters in attachment paths, for example ![[fig%23draft%5D.png]] for fig#draft].png; diagnostic suggestions do this automatically.

Full paths from the vault root

Set link_format = "absolute" in foamwiki.toml to use full vault-relative note IDs and links such as [[users/nima/model]], [[users/nima/model.md#Setup|Configuration]], and ![[users/nima/model#^result]]. Folder-qualified wikilinks resolve only from the vault root in this mode; a missing users/nima/model does not fall back to archive/users/nima/model. Basename links still resolve when unambiguous, and fix expands them to the preferred full path. Directory-index links remain available when directory_mode is enabled. Explicit ./ and ../ paths keep their source-relative meaning, and ordinary Markdown links keep their existing path semantics.

This uses Obsidian's documented folder-path syntax. In Obsidian, select Settings > Files and links > New link format > Absolute path in vault to generate that spelling. Foampy's strict missing-path behavior is an explicit workspace policy; it is not a claim about undocumented Obsidian fallback behavior. Foampy does not read or change Obsidian settings.

The default link_format = "shortest" retains global shortest-ID and suffix lookup. In either mode, validation, fix, and coordinated note, heading, and block renames preserve intentional full vault-relative links, including an explicitly written note extension. Meaningful display text and embed markers survive renames. Redundant display text is still reported and removable by fix.

Workspace-wide operations verify that the effective configuration, indexed file census, and every indexed note still match the loaded snapshot. Applied mutations also reject symlink-backed write sources, stage all output before changing the workspace, and roll back on write or reload failure. A dry run therefore remains safe to review even while another editor is active: replanning or applying it fails loudly instead of overwriting newer content.

Selective indexing below an excluded directory

Exclusions use ordered Gitignore syntax. A rooted negation can re-include a narrow subtree without disabling pruning for unrelated excluded directories:

{
  "foam.files.exclude": ["!.agents/skills/**/*.md"]
}

foamwiki descends only through .agents/skills for this pattern; excluded siblings such as .agents/sessions remain pruned. Negations without a safe rooted prefix, such as !**/skills/**/*.md, retain conservative full-tree traversal so their matching behavior remains correct.

Compact notebook output

Public records use compact, payload-free representations while keeping identifiers and paths intact. Potentially large text fields are bounded. Search hits center an 88-character excerpt on the match instead of dumping the complete source line and nested Note/Pos records:

<Hit alphafold-2/paper L272:550 '...colaboratory). TM-align v. 20190822 (https://zhanglab.dcmb.med.umich.edu/...'>

Rows, SearchResults, tag indexes, document outlines, and node child menus display at most 20 entries and report how many remain. Slice them to continue. Literal SearchResults also materialize public hit records only on access; call .materialize() for an eager Rows[Hit]. Automatic mutation diff previews are bounded; call ChangeSet.diff() for the complete diff. These limits affect display only: Hit.text and Match.line retain the exact source line (including indentation), while record fields, iteration, and .to_df() retain complete data. Passage remains intentionally unbounded because evaluating .body or .read() is an explicit request for content.

Template authoring

Markdown templates can declare foam_template.filepath and use Foam variables in both their content and destination. Preview first, then repeat the reviewed call with dry_run=False:

draft = foamwiki.create(
    ws,
    template="meeting-scratchpad",
    when="2026-07-15T14:30:00+01:00",
    dry_run=True,
)
draft.path, draft.frontmatter, draft.text

note = foamwiki.create(
    ws,
    template="meeting-scratchpad",
    when="2026-07-15T14:30:00+01:00",
    dry_run=False,
)

foamwiki.daily(ws, "2026-07-15", dry_run=True) uses daily-note.md and prefers its template filepath. Explicit destinations always override template metadata.

Structure-aware reading (for notebook agents)

Read a large markdown file without dumping it into context. foamwiki.read returns a priced, navigable map of the file's sections — orient cheaply, drill by stable numeric path, search to a section, then read only what you choose:

doc = foamwiki.read("design.md")     # (or note.doc for a vault note — no reparse)
doc                                # repr = a priced table-of-contents (~150 tok for a 40k-tok file)
doc["3.2"]                         # drill by numeric path (or doc["Method"] / doc[3]); prints a menu, never dumps
doc.search("KL")                   # term -> the sections that contain it (Rows[Match])
doc["3.2"].body                    # read just this section's prose (a priced Passage); .read() for the whole subtree
doc["3.2"].children                # tree nav as properties: .parent .children .siblings .next .prev

Every view quotes exact line counts + ~token estimates, so you budget before you spend. Works standalone on any .md file (no workspace needed).

See AGENTS.md for the design philosophy and the placement rule. pandas and networkx are optional extras used lazily by .to_df() and to_networkx(); request the all extra in the Git dependency when needed: foam-wiki[all] @ git+https://github.com/nimashoghi/foampy.git.

Development

uv sync
uv run pytest -q
uv run ruff check .
uv run basedpyright src scripts
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test --all-targets --all-features

See PERFORMANCE.md for the real-workspace baseline and reproducible benchmark command. MIGRATION.md lists the intentional behavior and naming changes. RELEASING.md documents local and CI release validation.

MIT licensed.

Commit checks

foamwiki check explicitly checks the working tree. For the exact content about to be committed, use:

foamwiki check --staged
foamwiki check --staged --new-only

The staged checker reads the active Git index and Git blobs directly. It checks the full selected graph, including unchanged notes whose destinations changed, without walking or modifying the worktree. Configuration and symlinks also come from the snapshot. Attachment contents are not read. Links outside the snapshot cannot resolve; selected notes stored as Git LFS pointers make the check incomplete. --new-only compares with HEAD using source path, diagnostic code, message, and occurrence count, so moving an existing problem to another line stays quiet. An initial commit has an empty baseline. Renamed source notes count as new source paths.

Install an advisory Git pre-commit hook in each clone with:

uv tool install foam-wiki==0.6.1
foamwiki install-hook

The installer requires POSIX and keeps the current Python environment's absolute executable path. Keep that environment available; rerun installation after moving the clone or replacing the environment. Git hooks run the prepared environment directly, without uv, downloads, daemons, watchers, or validation caches. New findings are printed with source locations and commits continue. Check failures visibly report check incomplete; they also allow the commit. Explicit checks exit 1 for findings (warnings require --strict) and 2 when incomplete.

Installation sets repository-local core.hooksPath and forwards the existing hook suite, including Git LFS, to its original scripts. Original exit statuses, arguments, stdin, environment, and working directory are preserved; an existing pre-commit failure still blocks the commit. Repeated installation is idempotent and concurrent installers do not wait. If changing the upstream hook directory later, set the desired core.hooksPath and rerun foamwiki install-hook. Git's --no-verify bypass remains available. See Git's hook contract.

Agent event hooks and the agent-hooks extra were removed in 0.6.1. Remove their old registrations from agent settings when upgrading. All other graph operations remain explicit library or CLI calls.

Metadata

Release files for foam-wiki 0.6.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for foam-wiki 0.6.1
File Size Uploaded
foam_wiki-0.6.1.tar.gz 206.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for foam-wiki 0.6.1
File
foam_wiki-0.6.1-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
foam_wiki-0.6.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
foam_wiki-0.6.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details
foam_wiki-0.6.1-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
foam_wiki-0.6.1-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 5.9 MB

Release files / foam_wiki-0.6.1.tar.gz

Download URL foam_wiki-0.6.1.tar.gz
Size 206.3 kB
Tags Source
SHA-256 checksum
How to use checksums
04ae1ac3ff6582922621a3b90a65103f8e21bbc5fcc0717d4c21e88884391f23
BLAKE2b-256 checksum
How to use checksums
b0b6a347483dc08332fa406fe911fddd31bcfbc0fca8a4b5f61911ea8814b80c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / foam_wiki-0.6.1-cp310-abi3-win_amd64.whl

Download URL foam_wiki-0.6.1-cp310-abi3-win_amd64.whl
Size 1.1 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
36cd69d051d5bb24f39881361899fb66f18a80974448d4ae2961bcdd3834feff
BLAKE2b-256 checksum
How to use checksums
323899dd2781e5a872438f0ccdf66cf9f21dd9677b7ccc900de38564ffab19c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / foam_wiki-0.6.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL foam_wiki-0.6.1-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.2 MB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
d3d3d45e96dd845529d1a53c36b29bfa2dab1c5e33df25c20a8520e0265963b2
BLAKE2b-256 checksum
How to use checksums
0f87f94c612eea3c770f38efbeb5885de90dfebf67bf592e7923f6c8cc4b60d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / foam_wiki-0.6.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL foam_wiki-0.6.1-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.1 MB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
44682425f57c2f210a478f8cec6aa39b48ed21664edbcfe7b332564741948561
BLAKE2b-256 checksum
How to use checksums
3246a4bde010d303c1f98876315dd7c65f57bc9e9c4460860a74210483d0c973
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / foam_wiki-0.6.1-cp310-abi3-macosx_11_0_arm64.whl

Download URL foam_wiki-0.6.1-cp310-abi3-macosx_11_0_arm64.whl
Size 1.1 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
53bf41968d308be77a30361d7ad5544579ca39a08d88170c19f3b192d24109b4
BLAKE2b-256 checksum
How to use checksums
b8438f60ff5f2794fdd9a4389def401d2063caa7937f9c70b094dd04576280ba
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log

Release files / foam_wiki-0.6.1-cp310-abi3-macosx_10_12_x86_64.whl

Download URL foam_wiki-0.6.1-cp310-abi3-macosx_10_12_x86_64.whl
Size 1.1 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
98e2af8bf57c3e752378e51072ab1c2fa89aa2f1b849d0589aaaf008033a8115
BLAKE2b-256 checksum
How to use checksums
a3f99d39d1a15bf193c34c3be900ab6ec20e6dd1cc87cb5f0811c73220c915d8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 24, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page