Skip to main content

mdfsrun

One Markdown file = one runnable project. Think of it as PEP 723 grown up to several files and a task runner:

  • the front matter is a Taskfile,
  • the body is documentation plus fenced code blocks marked with a file path,
  • the code blocks are extracted into a work directory with Entangled, and the tasks run there.

All you need is uv. Task, Entangled and Python itself are fetched by uv.

---
tasks:
  default:
    cmds:
      - uv run main.py
  test:
    cmds:
      - uv run --with pytest python -m pytest -q
---

# Hello

```python {.python file=main.py}
# /// script
# dependencies = ["rich"]
# ///
from pkg.core import greet
greet("world")
```

```python {.python file=pkg/core.py}
from rich import print

def greet(name: str) -> None:
    print(f"[bold green]Hello, {name}![/bold green]")
```

```python {.python file=pkg/__init__.py}
```
uvx mdfsrun app.md          # runs the "default" task
uvx mdfsrun app.md test     # runs the "test" task

Usage

mdfsrun [--rm] FILE.md [TASK ...] [VAR=VALUE ...] [task options ...]

Everything after the .md file is passed to task unchanged, so uvx mdfsrun app.md --list-all works too. Options of mdfsrun itself go before the .md file.

Option / variable Meaning
--rm / MDFSRUN_RM=1 delete the work directory after the run
MDFSRUN_DIR use this work directory instead of .mdfsrun/<name>/ next to the .md

How it works

  1. The .md is copied into the work directory (.mdfsrun/<name>/ next to the .md by default) and Entangled extracts the code blocks there. The work directory gets a .gitignore containing *, so Git ignores it.
  2. The front matter is passed to task as the Taskfile, and the tasks run in the work directory. version: '3' is added if the front matter has no version.

Tasks receive these environment variables. Use them in templates ({{.MD_DIR}}) or in commands ($MD_DIR):

Variable Value
MD absolute path of the .md
MD_DIR absolute path of the directory containing the .md
OUT absolute path of the work directory

For example, to load a .env that sits next to the .md:

dotenv: ["{{.MD_DIR}}/.env"]

The work directory is kept after the run, but it is rebuilt from the .md every time: files edited there are reset, and files whose block was removed from the .md are deleted. Files created by the tasks themselves (such as .venv) are left alone. mdfsrun refuses to use (or delete) an existing non-empty directory it did not create.

Code blocks

A code block is extracted when its attributes contain file=. Both forms work:

```python {.python file=main.py}
```

``` {.python file=main.py}
```

Blocks without {...} (```sh, ```python) are plain documentation. Only fences of exactly three backticks are recognized, so a Markdown file that itself contains file= blocks cannot be embedded.

Using Entangled locally

The .md is the single source of truth: edit the .md, not the files in the work directory. Writing changes back from the work directory (entangled stitch) is not supported; the files there carry no annotations.

You can still run Entangled yourself next to the .md, including entangled stitch. Put this entangled.toml next to the .md:

version = "2.0"
ignore_list = [".mdfsrun/**/*"]

[markers]
open  = '^(?P<indent>\s*)```[^\s{`]*\s*\{(?P<properties>[^{}]*)\}\s*$'
close = '^(?P<indent>\s*)```\s*$'
  • [markers] makes Entangled accept the ```python {.python file=...} form (the same config as mdfs).
  • ignore_list keeps Entangled away from .md files that a run may have extracted into the work directory. It is not needed if you use --rm or a MDFSRUN_DIR outside the project.

mdfsrun always runs what is in the .md; changes you have not stitched back are not used.

Notes

  • Requires Python 3.13 or later (a requirement of Entangled 2.4.x); uv installs it if needed.
  • The first run downloads Task, Entangled and the dependencies of your code; later runs use uv's cache.
  • Running an .md file runs whatever its front matter and code say. Only run files you trust.

License

MIT

Metadata

Release files for mdfsrun 0.1.3

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

Source distribution (sdist)

Source distribution for mdfsrun 0.1.3
File Size Uploaded Provenance Actions
mdfsrun-0.1.3.tar.gz 6.6 kB Without provenance Details for mdfsrun-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mdfsrun 0.1.3
File Interpreter ABI Platform Actions
mdfsrun-0.1.3-py3-none-any.whl Python 3 none any Details for mdfsrun-0.1.3-py3-none-any.whl

Total release size: 14.4 kB

Release files / mdfsrun-0.1.3.tar.gz

Download URL mdfsrun-0.1.3.tar.gz
Size 6.6 kB
Tags Source
SHA-256 checksum
How to use checksums
0c209cbb14ea0b1dae00b7b83698c70f865d58549c7d18709ff60f952fbddbbb
BLAKE2b-256 checksum
How to use checksums
64cb4a490797840b765c555d8270508f2d41f4557074cdddd6670fe3826870ec
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / mdfsrun-0.1.3-py3-none-any.whl

Download URL mdfsrun-0.1.3-py3-none-any.whl
Size 7.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
006bed156eee18a2eb3b3e87e2973a96a323b6ea4ef0512908903ef5e385ab52
BLAKE2b-256 checksum
How to use checksums
3d361b4e46989163fbc9a77cc2f282f7bf8caf65a77c0d530758d9a6bf8f5d38
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Security for mdfsrun 0.1.3

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files No provenance

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