Skip to main content

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.

PyPI version CI

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 like slug).
  • Strictness Flags: In your config.yaml, use optional: true for warnings instead of errors, silent: true to suppress warnings, or authorize: false to 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

skelantic-0.1.1.tar.gz (36.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

skelantic-0.1.1-py3-none-any.whl (25.8 kB view details)

Uploaded Python 3

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

Hashes for skelantic-0.1.1.tar.gz
Algorithm Hash digest
SHA256 2c3f7b75676850b9d8f2fbead87fd6416856f12411b0f813375d1b4d3cfd2064
MD5 980c489035497667ffc5ba3827846e49
BLAKE2b-256 eb1d364f00595cbffb1740f2f870c20239c9d399e1083b665f039357e43c658f

See more details on using hashes here.

Provenance

The following attestation bundles were made for skelantic-0.1.1.tar.gz:

Publisher: ci.yml on ghackenberg/skelantic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for skelantic-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5b344c17e301617e755a6f4b684b7c628ef58ea320b16a2b232dbbf75024dea5
MD5 68062a0913d2178f1d184b7e1b10f4b6
BLAKE2b-256 53b2069cdd5c21ef6c9e618932332e92e6826f81c1f27788403754386f783c78

See more details on using hashes here.

Provenance

The following attestation bundles were made for skelantic-0.1.1-py3-none-any.whl:

Publisher: ci.yml on ghackenberg/skelantic

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page