Declarative filesystem policy checks for repositories, release bundles, and CI gates. https://clawlter.mehalter.page/policyglass/
Find a file
Clawlter Agent 08b762208c
All checks were successful
CI / Validate lint, typing, tests, docs, and build (push) Successful in 3m16s
fix(ci): load bootstrap helpers without runtime deps
2026-04-19 13:09:47 +00:00
.forgejo/workflows feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
.github/workflows feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
docs feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
examples feat: bootstrap policyglass 2026-04-18 00:37:26 +00:00
plans feat: bootstrap policyglass 2026-04-18 00:37:26 +00:00
policies feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
scripts fix(ci): load bootstrap helpers without runtime deps 2026-04-19 13:09:47 +00:00
src/policyglass feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
tests fix(ci): load bootstrap helpers without runtime deps 2026-04-19 13:09:47 +00:00
.gitignore feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
CHANGELOG.md release: standardize package publish and install docs 2026-04-18 03:58:13 +00:00
CONTRIBUTING.md release: standardize package publish and install docs 2026-04-18 03:58:13 +00:00
LICENSE feat: bootstrap policyglass 2026-04-18 00:37:26 +00:00
mkdocs.yml ci: add Forgejo automation and docs publishing 2026-04-18 02:21:55 +00:00
pyproject.toml feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
README.md feat(ci): dogfood policyglass in repo workflows 2026-04-19 13:02:01 +00:00
SECURITY.md feat: bootstrap policyglass 2026-04-18 00:37:26 +00:00

Policyglass

Policyglass is a production-oriented Python CLI and library for validating a directory tree against a declarative YAML policy.

It is built for teams that want a lightweight guardrail in local workflows, CI, or release packaging without writing custom shell scripts for every repository.

What it checks

Policyglass currently supports four classes of checks:

  • required paths — fail when expected files or directories are missing
  • forbidden globs — fail when a path matches a banned pattern
  • size limits — fail when matched files exceed a configured byte threshold
  • forbidden content patterns — fail when text content matches a dangerous or disallowed regex

Why use it

  • small and explicit configuration
  • typed Python API and a usable CLI
  • JSON output for automation and text output for humans
  • designed to fit pre-commit, CI, packaging, and release validation flows
  • straightforward extension surface for adding new rule types later

Install

Policyglass currently targets Python 3.13+.

python -m pip install \
  'https://code.mehalter.com/api/packages/clawlter/pypi/files/policyglass/0.1.1/policyglass-0.1.1-py3-none-any.whl'

This exact wheel URL was verified against the published Forgejo package registry release. Do not use a bare pip install policyglass: an unrelated package with the same name exists on public PyPI.

For local development in this repository:

uv venv .venv
uv pip install --python .venv/bin/python -e '.[dev]'

Quick start

Create a starter policy:

policyglass init policyglass.yml

Note: if the policy file lives under the scan target, it counts as part of the scanned tree like any other file.

Example policy:

version: 1
required_paths:
  - README.md
  - src/
forbidden_globs:
  - '*.pem'
  - '.env'
ignore_globs:
  - '.git/'
  - '.venv/'
size_limits:
  - glob: 'dist/*.whl'
    max_bytes: 10000000
forbidden_content_patterns:
  - pattern: 'AKIA[0-9A-Z]{16}'
    message: 'Possible AWS key'

Run a check:

policyglass check . --policy policyglass.yml

Machine-readable output:

policyglass check . --policy policyglass.yml --format json

CLI overview

policyglass check

Validate a directory tree against a policy file.

policyglass check PATH --policy policyglass.yml [--format text|json]

Exit codes:

  • 0 — no violations
  • 1 — one or more violations

policyglass init

Write a starter policy file.

policyglass init policyglass.yml

Use --force to overwrite an existing file.

Python API

from pathlib import Path

from policyglass import load_policy, scan_path

policy = load_policy(Path("policyglass.yml"))
report = scan_path(Path("."), policy)

if not report.passed:
    for finding in report.findings:
        print(finding.code, finding.path, finding.message)

Documentation

The docs site lives under docs/, is built with MkDocs Material, and is published at https://clawlter.mehalter.page/policyglass/.

Useful entry points:

  • docs/index.md
  • docs/getting-started.md
  • docs/reference/policy-file.md
  • docs/reference/cli.md
  • docs/guides/ci.md
  • docs/architecture.md

Build locally:

mkdocs build --strict

Serve locally:

mkdocs serve

Dogfooding in this repository

Policyglass validates this repository with its own policy file at policies/repository.yml.

That policy is intentionally narrow and operational:

  • require the core source, test, docs, and workflow paths that make this repo shippable
  • reject common secret-bearing file extensions like .pem, .key, .p12, and .env
  • ignore generated or local-only paths such as .git/, .venv/, .tools/, dist/, and site/

Run the same repository gate used in CI:

python scripts/install_latest_policyglass_release.py --install-dir .tools/policyglass-release
.tools/policyglass-release/bin/policyglass check . --policy policies/repository.yml

The first command resolves the latest published policyglass wheel from the Forgejo package registry on code.mehalter.com, creates a small local virtualenv, and installs that release there. CI uses the released package the same way instead of building Policyglass from the checkout just to validate the checkout.

Development

Run the main quality gates:

ruff check .
ruff format --check .
mypy src
pytest
mkdocs build --strict
python -m build

Release automation

  • Forgejo CI runs from .forgejo/workflows/ci.yml
  • docs validation runs from .forgejo/workflows/docs-site.yml
  • docs publishing runs from .forgejo/workflows/docs-deploy.yml
  • tag-based release publishing runs from .forgejo/workflows/release.yml

Repository validation now dogfoods Policyglass directly:

  • policies/repository.yml defines the repository-level guardrail
  • scripts/install_latest_policyglass_release.py resolves and installs the latest published release from the Forgejo package registry into .tools/policyglass-release
  • the Forgejo and GitHub CI workflows use that released binary to run policyglass check . --policy policies/repository.yml
  • the Forgejo release workflow also generates dist/checksums.txt and validates the built bundle with policies/release-artifacts.yml

Release publishing targets the Forgejo PyPI-compatible package registry at https://code.mehalter.com/api/packages/clawlter/pypi.

Automated publishing uses the shared user-level Forgejo Actions secret PACKAGE_TOKEN. Tagged pushes matching v* validate the tag/version match, run the full quality gates, smoke-test the built wheel, and upload the distribution.

Install from the Forgejo package registry with:

python -m pip install \
  'https://code.mehalter.com/api/packages/clawlter/pypi/files/policyglass/0.1.1/policyglass-0.1.1-py3-none-any.whl'

The direct wheel URL avoids ambiguity with the unrelated public PyPI package named policyglass while still letting pip resolve runtime dependencies normally.

Project status

Policyglass is intentionally small but production-minded:

  • typed modules
  • unit tests with coverage enforcement
  • CI workflow included
  • contributor and security documentation included
  • documentation website included

License

MIT. See LICENSE.