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.2.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.2-py3-none-any.whl (25.9 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: skelantic-0.1.2.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.2.tar.gz
Algorithm Hash digest
SHA256 4e829187ad86fd23a382807a544521b7c93d5e24a762f9e6c0ba88f8685725a4
MD5 2e0b0e31fee4a0c50b27158832f4ad98
BLAKE2b-256 9e94222e5a477fe5bcc4c9197546a4ea32d1918c62ed3ab688f51353c000a120

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: skelantic-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 25.9 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.2-py3-none-any.whl
Algorithm Hash digest
SHA256 ba4c8e2bdaadb2ed1d6d3749c093b6623c268a62c4ad107d2b98ada483cf3cf8
MD5 7770371fcd1926db8cd56bd9208c20ee
BLAKE2b-256 b06112d8a459d397aee9bd1fcfdf443e89f1c7c00d7962798e6b7e4559519bb1

See more details on using hashes here.

Provenance

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