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.0.tar.gz (39.1 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.0-py3-none-any.whl (26.0 kB view details)

Uploaded Python 3

File details

Details for the file skelantic-0.1.0.tar.gz.

File metadata

  • Download URL: skelantic-0.1.0.tar.gz
  • Upload date:
  • Size: 39.1 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.0.tar.gz
Algorithm Hash digest
SHA256 d395baaa6bdf10687a9e8322b0571db3a569fb006dcdf17964d376f5d1ef5d58
MD5 97a131bb7a09dc7a8d77e1a2f6671e16
BLAKE2b-256 5cc183de0f657b31352f54828535859bf9bdf5521f9db3c35d01830f158d71e2

See more details on using hashes here.

Provenance

The following attestation bundles were made for skelantic-0.1.0.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.0-py3-none-any.whl.

File metadata

  • Download URL: skelantic-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 26.0 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.0-py3-none-any.whl
Algorithm Hash digest
SHA256 407564d56914e64f84eb19b8535c02dbc49f9ed0c236acc265bf551e92bb70c3
MD5 6354851e8105236916d4d3a144919d24
BLAKE2b-256 55f78f5b30050042c28fc725228ac1ef2e99816318db468cbcc377763b61fde0

See more details on using hashes here.

Provenance

The following attestation bundles were made for skelantic-0.1.0-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