Executable Markdown Runtime – run and manage entire projects directly from a single README.md file using specialized markpact code blocks and isolated Docker sandboxes.
Project description
markpact - + GitOps meets AI Agents — all in one README.
Markpact to minimalny runtime, który pozwala trzymać cały projekt w jednym README.md.
Runtime ignoruje zwykły Markdown, a wykonuje wyłącznie codeblocki markpact:*.
💡 Czym jest Markpact?
Markpact to narzędzie, które zamienia plik README.md w wykonywalny kontrakt projektu. Zamiast utrzymywać osobno dokumentację i kod źródłowy, wszystko znajduje się w jednym miejscu.
Kluczowe możliwości:
| Funkcja | Opis |
|---|---|
| Executable README | Uruchom cały projekt z jednego pliku README.md |
| LLM Generation | Wygeneruj projekt z opisu tekstowego: markpact -p "REST API" |
| Live Demo | Interaktywne demo z generowaniem PDF: python examples/demo_live_markpact.py |
| PDF Generation | Automatyczne tworzenie PDF dokumentacji (7 stron) |
| Multi-language | Python, Node.js, Go, Rust, PHP, TypeScript, React |
| Publishing | Publikuj do PyPI, npm, Docker Hub jedną komendą |
| Docker Sandbox | Uruchom w izolowanym kontenerze: --docker |
| HTTP Testing | Definiuj testy HTTP w markpact:test http |
| Auto-fix | Automatyczne naprawianie błędów runtime |
| Sync & Rollback | Synchronizuj pliki źródłowe z README: markpact sync |
Dla kogo?
- Deweloperzy – szybkie prototypowanie i uruchamianie projektów
- DevOps – CI/CD z README jako single source of truth
- Edukatorzy – interaktywne tutoriale z wykonywalnym kodem
- LLM/AI – generowanie i modyfikacja projektów przez AI
🚀 Szybki start
git clone https://github.com/wronai/markpact.git
# Instalacja
pip install markpact[llm]
# Konfiguracja LLM (wybierz jeden)
markpact config --provider ollama # lokalny
markpact config --provider openrouter --api-key sk-or-v1-xxx # chmura
# Generuj i uruchom jedną komendą!
markpact -p "REST API do zarządzania zadaniami z SQLite" -o todo/README.md --run
markpact -p "URL shortener with FastAPI and SQLite" -o url-test/README.md --run
# Lub z gotowego przykładu
markpact -e todo-api -o todo/README.md --run
🎬 Demo Live - Generowanie z LLM w czasie rzeczywistym
Spróbuj interaktywnego demo, które generuje kompletny projekt z promptu i tworzy PDF dokumentacji:
# Wejdź do katalogu markpact
cd /home/tom/github/wronai/markpact
# Uruchom demo z własnym promptem
python examples/demo_live_markpact.py --prompt "Build a chat API with WebSocket"
# Lub użyj gotowego przykładu
python examples/demo_live_markpact.py --example todo-api
# Lista dostępnych przykładów
python examples/demo_live_markpact.py --list
Co robi demo:
- Generuje kontrakt z LLM (Ollama/OpenRouter/OpenAI)
- Parsuje bloki
markpact:*z wygenerowanego README - Waliduje wszystkie wymagane bloki
- Tworzy PDF z pełną dokumentacją (7 stron)
- Zapisuje wyniki do
generated/live/
Wymagania:
pip install markpact[llm] fpdf2
Przykład wyjścia:
[PASS] LLM wygenerował kontrakt 81.1s, 2177 znaków
[PASS] Znaleziono 4 bloków 0.0ms
[PASS] Zaleznosci: 3 pakietów fastapi, uvicorn, websockets
[PASS] Plik: app/main.py 36 linii
[PASS] PDF zapisany: generated/live/markpact_live_custom.pdf 13 KB, 7 stron
🤖 Generowanie z LLM
Wygeneruj kompletny projekt z opisu tekstowego:
# Lista 16 gotowych przykładów
markpact --list-examples
# Generuj z promptu
markpact -p "URL shortener z FastAPI i SQLite" -o url/README.md
# Generuj i uruchom natychmiast (one-liner)
markpact -p "Chat WebSocket z FastAPI" -o chat/README.md --run
# Uruchom w izolowanym Docker
markpact -p "Blog API z komentarzami" -o blog/README.md --run --docker
Obsługiwane providery: Ollama (lokalny), OpenRouter, OpenAI, Anthropic, Groq
Szczegóły: docs/generator.md
📦 Publikacja do rejestrów
Publikuj artefakty bezpośrednio z README:
# PyPI
markpact README.md --publish --bump patch
# npm
markpact README.md --publish --registry npm
# Docker Hub
markpact README.md --publish --registry docker
# GitHub Container Registry
markpact README.md --publish --registry ghcr
Obsługiwane rejestry: PyPI, npm, Docker Hub, GitHub Packages, GHCR
📓 Konwersja Notebooków
Konwertuj notebooki do formatu markpact:
# Lista obsługiwanych formatów
markpact --list-notebook-formats
# Konwersja Jupyter Notebook
markpact --from-notebook notebook.ipynb -o project/README.md
# Konwersja i uruchomienie
markpact --from-notebook notebook.ipynb -o project/README.md --run
# Podgląd konwersji
markpact --from-notebook notebook.ipynb --convert-only
Obsługiwane formaty:
| Format | Rozszerzenie | Opis |
|---|---|---|
| Jupyter Notebook | .ipynb |
Python, R, Julia |
| R Markdown | .Rmd |
R z markdown |
| Quarto | .qmd |
Wielojęzyczny |
| Databricks | .dib |
Python, Scala, R |
| Zeppelin | .zpln |
Python, Scala, SQL |
📚 Dokumentacja
- Pełna dokumentacja
- Demo Live Guide ⭐ NEW - Interaktywne demo z PDF
- Generowanie z LLM ⭐ NEW
- Kontrakt markpact:*
- CI/CD Integration
- Współpraca z LLM
🎯 Przykłady
| Przykład | Opis | Uruchomienie |
|---|---|---|
| Demo Live | Interaktywne generowanie z LLM + PDF | python examples/demo_live_markpact.py --prompt "Chat API" |
| FastAPI Todo | REST API z bazą danych | markpact examples/fastapi-todo/README.md |
| Flask Blog | Aplikacja webowa z szablonami | markpact examples/flask-blog/README.md |
| CLI Tool | Narzędzie linii poleceń | markpact examples/cli-tool/README.md |
| Streamlit Dashboard | Dashboard danych | markpact examples/streamlit-dashboard/README.md |
| Kivy Mobile | Aplikacja mobilna | markpact examples/kivy-mobile/README.md |
| Electron Desktop | Aplikacja desktopowa | markpact examples/electron-desktop/README.md |
| Markdown Converter | Konwersja zwykłego MD | markpact examples/markdown-converter/sample.md --convert |
| Go HTTP API | REST API w Go | markpact examples/go-http-api/README.md |
| Node Express API | REST API w Node.js | markpact examples/node-express-api/README.md |
| Static Frontend | Statyczny HTML/CSS/JS | markpact examples/static-frontend/README.md |
| Python Typer CLI | CLI w Python (Typer) | markpact examples/python-typer-cli/README.md |
| Rust Axum API | REST API w Rust | markpact examples/rust-axum-api/README.md |
| PHP CLI | CLI w PHP | markpact examples/php-cli/README.md |
| React TypeScript SPA | SPA React + TS | markpact examples/react-typescript-spa/README.md |
| TypeScript Node API | REST API w TS (Node) | markpact examples/typescript-node-api/README.md |
| PyPI Publish | Publikacja do PyPI | markpact examples/pypi-publish/README.md --publish |
| npm Publish | Publikacja do npm | markpact examples/npm-publish/README.md --publish |
| Docker Publish | Publikacja do Docker | markpact examples/docker-publish/README.md --publish |
| Notebook Converter | Konwersja .ipynb do markpact | markpact --from-notebook examples/notebook-converter/sample.ipynb --convert-only |
🧪 Testowanie przykładów
Uruchom automatyczne testy wszystkich przykładów:
# Dry-run (tylko parsowanie)
./scripts/test_examples.sh
# Pełne uruchomienie
./scripts/test_examples.sh --run
# Verbose output
./scripts/test_examples.sh --verbose
🔄 Sync — synchronizacja plików z README
Komenda sync aktualizuje bloki markpact:file w README.md na podstawie rzeczywistych plików w katalogu źródłowym (np. sandbox/). Odwrotność markpact pack.
# Synchronizacja (auto-detect sandbox/ obok README)
markpact sync README.md
# Z własnym katalogiem źródłowym
markpact sync README.md --source ./my-project
# Podgląd zmian bez zapisu
markpact sync README.md --dry-run --diff
# CI check — exit 1 jeśli pliki nie są zsynchronizowane
markpact sync README.md --check
# Lista śledzonych plików
markpact sync README.md --list
# Pliki w katalogu źródłowym nie śledzone w README
markpact sync README.md --missing
# Wyklucz wrażliwe pliki
markpact sync README.md --exclude .env --exclude .env.prod
Rollback — przywracanie poprzedniej wersji
Każdy sync automatycznie tworzy backup README w .markpact/ (max 10).
# Przywróć ostatni backup
markpact sync README.md --rollback
# Lista dostępnych backupów
markpact sync README.md --backups
# Przywróć konkretny backup
markpact sync README.md --rollback-to .markpact/README.md.bak.20240301_143022
Opcje markpact sync
| Flaga | Opis |
|---|---|
-n, --dry-run |
Podgląd bez zapisu |
-d, --diff |
Pokaż unified diff |
-c, --check |
CI: exit 1 jeśli out-of-sync |
-l, --list |
Lista śledzonych plików |
-m, --missing |
Pliki źródłowe bez bloku w README |
--exclude PATH |
Wyklucz plik (powtarzalne) |
--rollback |
Przywróć z ostatniego backup |
--rollback-to FILE |
Przywróć z konkretnego backup |
--backups |
Lista dostępnych backupów |
-s, --source DIR |
Katalog źródłowy (domyślnie: sandbox/) |
🔄 Konwersja zwykłego Markdown
Markpact może automatycznie konwertować zwykłe pliki Markdown (bez tagów markpact:*) do formatu wykonywalnego:
# Podgląd konwersji
markpact README.md --convert-only
# Konwersja i uruchomienie
markpact README.md --convert
# Auto-detekcja (konwertuj jeśli brak markpact blocks)
markpact README.md --auto
# Zapisz skonwertowany plik
markpact README.md --convert-only --save-converted output.md
Konwerter analizuje code blocks i na podstawie heurystyk wykrywa:
- Zależności →
markpact:deps(pakiety Python/Node) - Pliki źródłowe →
markpact:file(importy, klasy, funkcje) - Komendy →
markpact:run(python, uvicorn, npm, etc.)
1️⃣ Cel projektu
- Jedno README jako źródło prawdy
- Możliwość uruchomienia projektu bez ręcznego tworzenia struktury plików
- Automatyzacja Bootstrap tworzy pliki w sandboxie, instaluje zależności i uruchamia komendę startową.
2️⃣ Kontrakt README (codeblocki markpact:*)
markpact:bootstrap <lang>Dokładnie jeden bootstrap na README. Odpowiada za parsowanie codeblocków i uruchomienie.markpact:deps <scope>Lista zależności dla danego scope (np.python).markpact:file <lang> path=...Zapisuje plik do sandboxu pod ścieżkąpath=....markpact:run <lang>Jedna komenda uruchomieniowa wykonywana w sandboxie.
#!/usr/bin/env python3
"""MARKPACT v0.1 – Executable Markdown Runtime"""
import os, re, subprocess, sys
from pathlib import Path
README = Path(sys.argv[1] if len(sys.argv) > 1 else "README.md")
SANDBOX = Path(os.environ.get("MARKPACT_SANDBOX", "./sandbox"))
SANDBOX.mkdir(parents=True, exist_ok=True)
RE = re.compile(r"^```markpact:(?P<kind>\w+)(?:\s+(?P<meta>[^\n]+))?\n(?P<body>.*?)\n^```[ \t]*$", re.DOTALL | re.MULTILINE)
def run(cmd):
print(f"[markpact] RUN: {cmd}")
env = os.environ.copy()
venv = SANDBOX / ".venv" / "bin"
if venv.exists():
env.update(VIRTUAL_ENV=str(venv.parent), PATH=f"{venv}:{env.get('PATH','')}")
subprocess.check_call(cmd, shell=True, cwd=SANDBOX, env=env)
def main():
deps, run_cmd = [], None
for m in RE.finditer(README.read_text()):
kind, meta, body = m.group("kind"), (m.group("meta") or "").strip(), m.group("body").strip()
if kind == "file":
p = re.search(r"\bpath=(\S+)", meta)
if not p: raise ValueError(f"markpact:file requires path=..., got {meta!r}")
f = SANDBOX / p[1]
f.parent.mkdir(parents=True, exist_ok=True)
f.write_text(body)
print(f"[markpact] wrote {f}")
elif kind == "deps" and meta == "python":
deps.extend(line.strip() for line in body.splitlines() if line.strip())
elif kind == "run":
run_cmd = body
if deps:
venv_pip = SANDBOX / ".venv" / "bin" / "pip"
if os.environ.get("MARKPACT_NO_VENV") != "1" and not venv_pip.exists():
run(f"{sys.executable} -m venv .venv")
(SANDBOX / "requirements.txt").write_text("\n".join(deps))
run(f"{'.venv/bin/pip' if venv_pip.exists() else 'pip'} install -r requirements.txt")
if run_cmd:
run(run_cmd)
else:
print("[markpact] No run command defined")
if __name__ == "__main__":
main()
3️⃣ Instalacja
Opcja A: Pakiet pip (zalecane)
# Podstawowa instalacja
pip install markpact
# Z LLM i PDF generation (dla demo)
pip install markpact[llm] fpdf2
# Z integracją fixop (auto-fix, diagnostyka portów)
pip install markpact[ops]
Użycie:
markpact README.md # uruchom projekt
markpact README.md --dry-run # podgląd bez wykonywania
markpact README.md -s ./my-sandbox # własny katalog sandbox
# Demo live z LLM
python examples/demo_live_markpact.py --prompt "Twój prompt"
Opcja B: Instalacja lokalna (dev)
git clone https://github.com/wronai/markpact.git
cd markpact
make install # lub: pip install -e .
Opcja C: Ekstrakcja bootstrapu (zero dependencies)
-
Ekstrakcja bootstrapu do pliku
Ten wariant jest odporny na przypadek, gdy w samym bootstrapie występują znaki ``` (np. w regexie):
sed -n '/^```markpact:bootstrap/,/^```[[:space:]]*$/p' README.md | sed '1d;$d' > markpact.py
-
Uruchomienie
python3 markpact.py -
Konfiguracja (env vars)
MARKPACT_PORT=8001 MARKPACT_SANDBOX=./.markpact-sandbox python3 markpact.py
4️⃣ Sandbox i środowisko
MARKPACT_SANDBOXZmienia katalog sandboxu (domyślnie./sandbox).MARKPACT_NO_VENV=1Wyłącza tworzenie.venvw sandboxie (przydatne, jeśli CI/Conda zarządza środowiskiem).- Port zajęty (
[Errno 98] address already in use) UstawMARKPACT_PORTna inny port lub zatrzymaj proces, który używa8000.
5️⃣ Dependency management
- Python
Bootstrap zbiera
markpact:deps python, zapisujerequirements.txtw sandboxie i instaluje zależności.
6️⃣ Uruchamianie i workflow
- Wejście
python3 markpact.py [README.md] - Kolejność
Bootstrap parsuje wszystkie codeblocki, zapisuje pliki i dopiero na końcu uruchamia
markpact:run.
6.1 Konwencje i format metadanych
-
Nagłówek codeblocka
```markpact:<kind> <lang> <meta>Minimalnie wymagane jest
markpact:<kind>.langjest opcjonalny i pełni rolę informacyjną (bootstrap może go ignorować). -
Metadane Dla
markpact:filewymagane jestpath=.... Metadane mogą zawierać dodatkowe tokeny (np. w przyszłościmode=...,chmod=...).
6.2 CI/CD
-
Rekomendacja Uruchamiaj bootstrap w czystym środowisku (np. job CI) i ustaw sandbox na katalog roboczy joba.
-
Przykład (shell)
export MARKPACT_SANDBOX=./.markpact-sandbox export MARKPACT_PORT=8001 python3 markpact.py README.md
-
Wskazówki
- Deterministyczność
Pinuj wersje w
markpact:deps(np.fastapi==...). - Bezpieczeństwo
Traktuj
markpact:runjak skrypt uruchomieniowy repo: w CI odpalaj tylko zaufane README. - Cache
Jeśli CI wspiera cache, cache’uj katalog
MARKPACT_SANDBOX/.venv.
- Deterministyczność
Pinuj wersje w
6.3 Współpraca z LLM
- Zasada
LLM może generować/edytować projekt poprzez modyfikacje README (codeblocki
markpact:file,markpact:deps,markpact:run). - Oczekiwania
markpact:filezawsze zawiera pełną zawartość pliku.- Każda zmiana zależności idzie przez
markpact:deps. - Jedna komenda startowa w
markpact:run.
7️⃣ Najlepsze praktyki
- Bootstrap jako pierwszy fenced codeblock w README
- Każdy plik w osobnym
markpact:file - Zależności tylko w
markpact:deps - Jedna komenda startowa w
markpact:run - Ekstrakcja bootstrapu
Nie używaj zakresu
/,/```/(bomoże wystąpić w treści, np. w regexie). Używaj `^$` na końcu.
Plik konfiguracyjny (~/.markpact/.env)
# Markpact LLM Configuration
MARKPACT_MODEL="openrouter/nvidia/nemotron-3-nano-30b-a3b:free"
MARKPACT_API_BASE="https://openrouter.ai/api/v1"
MARKPACT_API_KEY="sk-or-v1-xxxxx"
MARKPACT_TEMPERATURE="0.7"
MARKPACT_MAX_TOKENS="4096"
Obsługiwani providerzy LLM
Ollama (lokalny, domyślny)
markpact config --provider ollama
markpact config --model ollama/qwen2.5-coder:14b
markpact -p "REST API dla książek"
OpenRouter (darmowe modele!)
markpact config --provider openrouter --api-key sk-or-v1-xxxxx
markpact config --model openrouter/nvidia/nemotron-3-nano-30b-a3b:free
markpact -p "REST API dla książek"
Działający przykład (FastAPI)
1️⃣ Dependencies
markpact:deps python
fastapi
uvicorn
2️⃣ Application Files
markpact:file python path=app/main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"message": "Hello from Executable Markdown"}
3️⃣ Run Command
markpact:run python
uvicorn app.main:app --host 0.0.0.0 --port ${MARKPACT_PORT:-8088}
🏗️ Architektura modułów
Markpact jest podzielony na małe, niezależne moduły:
src/markpact/
├── cli/ # CLI dispatch + subcommands
│ ├── __init__.py # main() — thin dispatch (CC≤5)
│ ├── sync_cmd.py # markpact sync
│ ├── pack_cmd.py # markpact pack
│ ├── config_cmd.py # markpact config
│ ├── publish_cmd.py # --publish mode
│ ├── run_cmd.py # normal run, Docker, test
│ ├── convert_cmd.py # notebook/markdown conversion
│ └── helpers.py # shared CLI utilities
├── publish/ # Multi-registry publisher
│ ├── models.py # PublishConfig, PublishResult
│ ├── helpers.py # inference, interactive config
│ ├── version.py # semver bump, extract, update
│ ├── llm_config.py # LLM-based config generation
│ ├── pypi.py # PyPI publisher
│ ├── npm.py # npm publisher
│ ├── docker_pub.py # Docker publisher
│ ├── github.py # GitHub Packages publisher
│ └── main.py # parse_publish_block, dispatch
├── auto_fix.py # Runtime error auto-fix (fixop integration)
├── parser.py # markpact:* block parser
├── syncer.py # README ↔ source sync
├── packer.py # Directory → README packer
├── sandbox.py # Isolated sandbox management
├── runner.py # Command execution
└── generator.py # LLM contract generation
Opcjonalne zależności
| Extra | Pakiet | Opis |
|---|---|---|
[llm] |
litellm | Generowanie kontraktów przez LLM |
[ops] |
fixop | Diagnostyka portów, klasyfikacja błędów |
[dev] |
pytest, ruff, build, twine | Narzędzia deweloperskie |
License
Apache License 2.0 - see LICENSE for details.
Author
Created by Tom Sapletta - tom@sapletta.com
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 markpact-0.1.36.tar.gz.
File metadata
- Download URL: markpact-0.1.36.tar.gz
- Upload date:
- Size: 93.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af7f9f6006136580ec53bbd74a3559423ccc77386175f9e61cd2e4d462417156
|
|
| MD5 |
d4b6d262327749c0f5c48faf8b97ed07
|
|
| BLAKE2b-256 |
99c7ba5b142be0c5d6b604ded3de30e9e2be7d894da74c385ff39b49b4f82892
|
File details
Details for the file markpact-0.1.36-py3-none-any.whl.
File metadata
- Download URL: markpact-0.1.36-py3-none-any.whl
- Upload date:
- Size: 82.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
186dd84827709702b645e64cd3300a7d3441f8b9d82db84abbead5b9a00a6817
|
|
| MD5 |
f8c8cf1df1b418afa50428af7ce0d896
|
|
| BLAKE2b-256 |
79060671f8f70627764f01bf0adfabccdbe9338fddf6c9aef4fbff0f18d2ca6c
|