A declarative repository governance and automation framework using skeletal templates and Pydantic.
Project description
Skelantic
A declarative file-tree processing and governance engine for Python.
Skelantic allows you to enforce repository structures, parse unstructured text files (like Markdown) into strictly typed Pydantic models using "Skeletal Templates", and execute Python-based processor functions over your file tree to ensure referential integrity and consistency.
It is particularly useful for:
- AI Coding Agents: Providing strict guardrails and architecture enforcement for autonomous agents.
- Documentation Governance: Ensuring that documentation folders conform to a specific structure and that cross-references are valid.
- Declarative Repositories: Managing complex, heavily structured projects (like Data Lakes, Content Management, or Architecture Decision Records) where files must adhere to strict templates.
🚀 Quick Start
1. Installation
Install Skelantic via pip:
pip install skelantic
2. Define the Repository Structure
Skelantic operates on a "Strict-by-Default" (Default-Deny) philosophy. By defining cascading .skelantic/config.yaml files throughout your repository, you explicitly allow files and directories. Anything not explicitly permitted is flagged as an error.
Create a .skelantic/config.yaml at the root of your project:
description: "Global configuration"
files:
"README.md":
description: "Main Readme"
directories:
"docs":
description: "Documentation directory"
directories:
"issues":
description: "Task tracking"
files:
"{slug}.md":
description: "An issue file"
template: ".skelantic/templates/issue.md"
3. Write a Skeletal Template
Skeletal Templates verify the contents of text files and extract data using a custom, readable AST. For a full list of available variables, block structures, and multiline extractions, see the Skeletal Templates Syntax Guide.
Create .skelantic/templates/issue.md:
# Issue: {{title:str}}
Status: {{status:enum[OPEN,IN_PROGRESS,DONE]}}
## Description
[[block:description]]
{{text}}
[[/block]]
4. Generate Pydantic Models
Before writing your custom logic, use the Skelantic CLI to automatically generate strongly-typed Pydantic models from your Skeletal Templates:
skelantic generate -o "my_project/models"
This will create Python files (e.g., my_project/models/issue.py) containing the strictly-typed representation of your template:
# Auto-generated by Skelantic
from pydantic import BaseModel
from typing import Optional
class IssueTemplate(BaseModel):
title: Optional[str] = None
status: Optional[str] = None
description: Optional[str] = None
5. Write Processors
Processors are written in pure Python and execute validation logic. Use the @processor decorator to bind them to specific files matching a glob pattern.
Skelantic automatically instantiates your generated Pydantic models and injects them, along with context and trace loggers, directly into your function. For a deep dive into the injected parameters, the different phases, and cross-file relational checks, see Writing Processors & Understanding Context and the File System Nodes API.
from typing import List, Callable, cast
from skelantic.commons.decorators import processor
from skelantic.commons.context import LinterContext
from skelantic.commons.nodes import FileNode
from my_project.models.issue import IssueTemplate # Your generated model!
@processor(match="docs/issues/*.md", phase=2)
def validate_issue_status(node: FileNode, ctx: LinterContext, tracer: Callable[[str], None] = lambda x: None) -> List[str]:
tracer(f"Validating issue: {node.rel_path.name}")
# 1. Fetch the raw data extracted from the template
full_path = node.rel_path.as_posix()
data = ctx.extracted_data.get(full_path, {})
if not data:
return []
# 2. Cast the raw data into your strictly-typed Pydantic model
model = IssueTemplate.model_validate(data)
# 3. Perform type-safe business logic validations
if model.status == "DONE" and not "resolution" in (model.description or "").lower():
return ["DONE issues must have a resolution in their description."]
# You can also use ctx.extracted_data to iterate through other files in the workspace
# to perform relational checks (e.g. checking if linked files exist).
return []
6. Run the Engine
Use the Skelantic CLI to execute the workflow engine against your repository.
# Run the engine to validate the repository
# -p specifies the package containing your @processor functions
# -m specifies the package containing your generated Pydantic models
skelantic run -p "my_project.processors" -m "my_project.models"
⚙️ Advanced Features
- Dependency Injection: The engine automatically injects arguments into your processor functions based on their signature (
node,ctx,tracer, and dynamic path variables likeslug). - Strictness Flags: In your
config.yaml, useoptional: truefor warnings instead of errors,silent: trueto suppress warnings, orauthorize: falseto apply patterns without implicitly authorizing existence. - Pydantic Integration: Skelantic natively supports Pydantic. If you map a Pydantic model to a template, the engine will automatically instantiate and inject the strongly-typed model into your processors.
🤝 Contributing
If you want to contribute to the development of the Skelantic engine itself, please see our CONTRIBUTING.md guide.
📚 More Documentation
Project details
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 skelantic-0.1.1.tar.gz.
File metadata
- Download URL: skelantic-0.1.1.tar.gz
- Upload date:
- Size: 36.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c3f7b75676850b9d8f2fbead87fd6416856f12411b0f813375d1b4d3cfd2064
|
|
| MD5 |
980c489035497667ffc5ba3827846e49
|
|
| BLAKE2b-256 |
eb1d364f00595cbffb1740f2f870c20239c9d399e1083b665f039357e43c658f
|
Provenance
The following attestation bundles were made for skelantic-0.1.1.tar.gz:
Publisher:
ci.yml on ghackenberg/skelantic
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skelantic-0.1.1.tar.gz -
Subject digest:
2c3f7b75676850b9d8f2fbead87fd6416856f12411b0f813375d1b4d3cfd2064 - Sigstore transparency entry: 1147447440
- Sigstore integration time:
-
Permalink:
ghackenberg/skelantic@2ee8c456f3baa5c911c3ed8d69206b21c86b71d2 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/ghackenberg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@2ee8c456f3baa5c911c3ed8d69206b21c86b71d2 -
Trigger Event:
push
-
Statement type:
File details
Details for the file skelantic-0.1.1-py3-none-any.whl.
File metadata
- Download URL: skelantic-0.1.1-py3-none-any.whl
- Upload date:
- Size: 25.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b344c17e301617e755a6f4b684b7c628ef58ea320b16a2b232dbbf75024dea5
|
|
| MD5 |
68062a0913d2178f1d184b7e1b10f4b6
|
|
| BLAKE2b-256 |
53b2069cdd5c21ef6c9e618932332e92e6826f81c1f27788403754386f783c78
|
Provenance
The following attestation bundles were made for skelantic-0.1.1-py3-none-any.whl:
Publisher:
ci.yml on ghackenberg/skelantic
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
skelantic-0.1.1-py3-none-any.whl -
Subject digest:
5b344c17e301617e755a6f4b684b7c628ef58ea320b16a2b232dbbf75024dea5 - Sigstore transparency entry: 1147447575
- Sigstore integration time:
-
Permalink:
ghackenberg/skelantic@2ee8c456f3baa5c911c3ed8d69206b21c86b71d2 -
Branch / Tag:
refs/tags/v0.1.1 - Owner: https://github.com/ghackenberg
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@2ee8c456f3baa5c911c3ed8d69206b21c86b71d2 -
Trigger Event:
push
-
Statement type: