See also: README Specification Network Configuration
Automatically generate saas.pactown.yaml by scanning a folder of markpact README files.
# Scan folder to see detected services
pactown scan ./examples
# Generate config from folder
pactown generate ./examples -o my-ecosystem.pactown.yaml
# With custom name and port
pactown generate ./examples --name my-platform --base-port 9000 -o config.yaml
Given this folder structure:
examples/
├── api/
│ └── README.md # markpact service
├── database/
│ └── README.md # markpact service
└── frontend/
└── README.md # markpact service
Running:
pactown generate ./examples -o ecosystem.pactown.yaml
Produces:
name: examples
version: 0.1.0
description: Auto-generated from examples
base_port: 8000
sandbox_root: ./.pactown-sandboxes
registry:
url: http://localhost:8800
namespace: default
services:
api:
readme: examples/api/README.md
port: 8001
health_check: /health
database:
readme: examples/database/README.md
port: 8000
health_check: /health
frontend:
readme: examples/frontend/README.md
port: 8002
health_check: /
The generator:
README.md files recursivelypactown.markpact_blocks.parse_blocks()markpact:run command)markpact:test http blocks)markpact:deps)Source: generator.py
pactown scanShow detected services without generating config:
$ pactown scan ./examples/saas-platform/services
Services found in ./examples/saas-platform/services
┏━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━┳━━━━━━━━━┳━━━━━━┓
┃ Name ┃ Title ┃ Port ┃ Health ┃ Deps ┃
┡━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━╇━━━━━━━━━╇━━━━━━┩
│ api │ API Backend │ auto │ /health │ 2 │
│ database │ Database Service │ 8003 │ /health │ 0 │
│ gateway │ API Gateway │ 8000 │ /health │ 3 │
│ web │ Web Frontend │ 8002 │ /health │ 0 │
└──────────┴──────────────────┴──────┴─────────┴──────┘
pactown generateGenerate configuration file:
pactown generate FOLDER [OPTIONS]
Options:
-n, --name TEXT Ecosystem name (default: folder name)
-o, --output TEXT Output file (default: saas.pactown.yaml)
-p, --base-port INT Starting port (default: 8000)
from pactown.generator import scan_folder, generate_config, scan_readme
# Scan single README
config = scan_readme(Path("./api/README.md"))
print(config)
# {
# 'name': 'api',
# 'readme': './api/README.md',
# 'port': 8001,
# 'health_check': '/health',
# 'deps': ['fastapi', 'uvicorn'],
# 'has_run': True,
# 'title': 'API Backend'
# }
# Scan folder
services = scan_folder(Path("./examples"))
for svc in services:
print(f"{svc['name']}: port={svc['port']}")
# Generate full config
config = generate_config(
folder=Path("./examples"),
name="my-platform",
base_port=9000,
output=Path("config.yaml"),
)
The generator looks for port in markpact:run blocks:
```bash markpact:run
uvicorn main:app --port ${MARKPACT_PORT:-8001}
```
Patterns matched:
--port ${MARKPACT_PORT:-8001} → 8001--port 8080 → 8080:3000 → 3000PORT=5000 → 5000Extracted from markpact:test http blocks:
```http markpact:test
GET /health EXPECT 200
GET /api/users EXPECT 200
```
Detects: /health (preferred) or first GET / endpoint.
From markpact:deps blocks:
```python markpact:deps
fastapi
uvicorn
httpx
```
For complex dependencies, manually edit the generated YAML.
markpact:test http blocks--port ${MARKPACT_PORT:-8001} for flexibility