F2K Markdown source compiler: structured, composable .md → .f.md
Project description
fkmd — F2K Markdown
F2K Markdown is a Markdown source compiler designed for AI Agents and knowledge base maintenance. It lets you write Markdown like Python—bringing the modularity of programming languages to your documents.
In the AI Agent era, Markdown has become a new programming language, widely used in Agent Skills development, knowledge base construction, and system prompt management. However, as project complexity grows, plain text Markdown becomes hard to maintain:
- Concept Duplication: The same terminology, version number, or configuration appears in multiple places, violating the Single Source of Truth (SSOT) principle.
- Lack of Modularity: Unable to nest files, resulting in overly long files that are hard to read and reuse.
- Tedious Formatting: Step numbers and heading levels require manual adjustment when reorganizing content.
F2K Markdown solves this by introducing a lightweight compilation mechanism:
- Seamless Integration: Source files are ordinary
.mdfiles (identified by a#!fkmdheader), and the compiled output is pure.f.mdMarkdown that any renderer or AI Agent can read natively. - Variables & Expressions: Embed Python variables or expressions directly in text using
{python_expr}. - Code Block Execution: Execute Python logic within Markdown code blocks for data processing or environment initialization.
- File Nesting: Embed other Markdown files with automatic heading level indentation for true document modularity.
- Lenient Parsing: Syntax errors or undefined variables won't crash the compiler; they are output as plain text to ensure robustness.
In the demo above: The left side shows the
.mdsource file with variables and expressions, while the right side shows the.f.mdoutput being compiled in real-time.
Installation
Install globally via uv (recommended):
uv tool install fkmd
# or install into your project
uv add fkmd
Alternatively, install from source:
git clone https://github.com/f2k-ai/f2k-markdown.git
cd f2k-markdown
uv sync
uv run fkmd --version
Quickstart
- Start the watcher in your document root:
cd your-document-root
fkmd watch .
Note:
fkmd watchmay prompt to upgrade existing.mdfiles. This is optional but recommended. See CLI.
- Create a simple source file
docs/hello.md:
#!fkmd 0.1
{name="World"}
# Hello {name}!
- The compiled output is automatically generated at
.fkmd-output/docs/hello.f.md:
# Hello World!
For a real-world use case involving global variables, Python execution, and file embedding, see the Comprehensive Example below.
Syntax Cheatsheet
Inside any source .md file (with #!fkmd header):
| Source | Compiles to |
|---|---|
#!fkmd 0.1 |
(stripped — must be the first line) |
{name} |
str(name) from the entry-script namespace |
{1 + 2} |
Any single-line Python expression evaluated at compile time |
{name="a"} / {import math} |
A single-line Python statement |
{{anything}} |
Literal {anything} (escape) |
{@incr:section} |
DSL sugar: 1, 2, 3, … per counter name |
{@doc:other.md,section="API"} |
DSL sugar: inlines other.md (or a specific section) with headings automatically shifted |
```lang … ``` |
Markdown code blocks are exempt from parsing |
```lang @fkmd … ``` |
Opt back in to {...} substitution inside a single fenced block |
```python @exec … ``` |
Execute multi-line Python. Replaced by the last expression's value, or disappears if None |
CLI
fkmd watch [WATCH_DIR] [-o OUTPUT_DIR] [-e ENTRY] [--once] [-y/--yes]
fkmd convert DIR
fkmd revert PATH
fkmd watch: Continuously compile.md→.f.mdas files change.fkmd convert: Safely upgrade plain.mdfiles tofkmdsources. It adds the#!fkmdheader and escapes existing braces (e.g.,{to{{) to ensure your original content remains exactly unchanged after compilation.fkmd revert: Strict inverse offkmd convert. It strips the header and unescapes braces, restoring your files to their original plain Markdown state.
Programmatic API
fkmd is also a Python library. Use it when you want to compile sources in-memory without managing a file-system loop.
from fkmd import compile_string, compile_file, Compiler
# In-memory string → string
result = compile_string("hello {name}!", globals={"name": "World"})
print(result.text) # "hello World!"
# Single file → write to a path
compile_file(
"docs/api-reference.md",
globals={"version": "1.2.3"},
output="dist/api-reference.html.md",
)
# Long-lived Compiler
compiler = Compiler(entry=".fkmd-entry.py", base_dir="docs/")
result = compiler.compile_file("docs/system-prompt.md")
Comprehensive Example
Here is a full example demonstrating how to build a modular system prompt for an AI Agent using global variables, Python execution, and file embedding.
- Global Variables: Edit the entry script
.fkmd-entry.py:
agent_name = "CodeCopilot"
- Main Document: Create your source file
docs/00-quick-start.md:
#!fkmd 0.1
{doc_version="v1.0"}
> Document Version: {doc_version} -- local variable defined in this file
> Agent Name: {agent_name} -- global variable defined in .fkmd-entry.py
> Current Time: {import datetime; datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}
# System Prompt
You are {agent_name}, an advanced AI coding assistant.
## {@incr:main}. Initial Setup
```python @exec
def test_api_connection():
return "connected"
```
Your API connection status is: {test_api_connection()}.
**Do not proceed** if the status is not connected.
## {@incr:main}. Operating Procedures
### Step {@incr:agent_step}: Gather Context
Always read the relevant files first.
### Step {@incr:agent_step}: Plan
Formulate a plan before executing changes.
## {@incr:main}. API Reference
> Note: The embedded API documentation's heading levels are automatically aligned to sit under this section.
{@doc:00b-quick-start.md, section="API Endpoints"}
- Embedded Document: Create the embedded file
docs/00b-quick-start.md:
#!fkmd 0.1
# API Endpoints
## GET `/api/v1/status`
Check health status.
- Compiled Output: The output will be automatically generated at
.fkmd-output/docs/00-quick-start.f.md:
> Document Version: v1.0 -- local variable defined in this file
> Agent Name: CodeCopilot -- global variable defined in .fkmd-entry.py
> Current Time: 2026-05-15 17:36:02
# System Prompt
You are CodeCopilot, an advanced AI coding assistant.
## 1. Initial Setup
Your API connection status is: connected.
**Do not proceed** if the status is not connected.
## 2. Operating Procedures
### Step 1: Gather Context
Always read the relevant files first.
### Step 2: Plan
Formulate a plan before executing changes.
## 3. API Reference
> Note: The embedded API documentation's heading levels are automatically aligned to sit under this section.
### API Endpoints
#### GET `/api/v1/status`
Check health status.
Under the Hood
To understand how {python_expr} are evaluated, it helps to know the execution order during a compile pass:
- Entry Script Execution: Before any Markdown file is processed, the entry script (e.g.,
.fkmd-entry.py) is executed exactly once. Any variables, functions, or imports defined here become the shared global namespace for the entire compile pass. - File Compilation: Each
.mdsource file is then compiled. Each file gets its own fresh local namespace. - Expression Evaluation: When the compiler encounters
{expression}or a```python @execblock, it evaluates the Python code using the file's local namespace backed by the shared global namespace. This means you can read global variables anywhere, but local assignments (like{doc_version="v1.0"}) remain isolated to that specific file.
Roadmap
See the roadmap for the detailed features and issues.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fkmd-0.1.0.tar.gz.
File metadata
- Download URL: fkmd-0.1.0.tar.gz
- Upload date:
- Size: 39.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
20bdef2c77cb430e2b2b842aa9e932c58318e065501780e9e888386431f49f2f
|
|
| MD5 |
36014123d1dca1d5147c43db86334ba3
|
|
| BLAKE2b-256 |
1cd4d3aa8e7bfa4111e789d7234c55cb6524e64ad85278651cc42c7e7fd0cdda
|
Provenance
The following attestation bundles were made for fkmd-0.1.0.tar.gz:
Publisher:
publish.yml on AlbertZSCreator/f2k-markdown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fkmd-0.1.0.tar.gz -
Subject digest:
20bdef2c77cb430e2b2b842aa9e932c58318e065501780e9e888386431f49f2f - Sigstore transparency entry: 1547230098
- Sigstore integration time:
-
Permalink:
AlbertZSCreator/f2k-markdown@db3d7eb99ed7d3bf7f8112988844bed30be54f74 -
Branch / Tag:
refs/tags/release-v0.1.0 - Owner: https://github.com/AlbertZSCreator
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db3d7eb99ed7d3bf7f8112988844bed30be54f74 -
Trigger Event:
release
-
Statement type:
File details
Details for the file fkmd-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fkmd-0.1.0-py3-none-any.whl
- Upload date:
- Size: 43.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8bbd9bcd83118c213d7ebadf3fc92569527457e0c8a838b93f5645b228e0900b
|
|
| MD5 |
5752f9914ced500f752069d32efec7bf
|
|
| BLAKE2b-256 |
59b3912afe0bc2b419aeb212b7da88c50b36bcd8919833021515522280985201
|
Provenance
The following attestation bundles were made for fkmd-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on AlbertZSCreator/f2k-markdown
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fkmd-0.1.0-py3-none-any.whl -
Subject digest:
8bbd9bcd83118c213d7ebadf3fc92569527457e0c8a838b93f5645b228e0900b - Sigstore transparency entry: 1547230112
- Sigstore integration time:
-
Permalink:
AlbertZSCreator/f2k-markdown@db3d7eb99ed7d3bf7f8112988844bed30be54f74 -
Branch / Tag:
refs/tags/release-v0.1.0 - Owner: https://github.com/AlbertZSCreator
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@db3d7eb99ed7d3bf7f8112988844bed30be54f74 -
Trigger Event:
release
-
Statement type: