agentsclimarketplace

Trestle jinja templating

Skill ethanolivertroy/compliance-trestle-skills/skills/trestle-jinja-templating

Agent-portable Compliance Trestle and OSCAL engineering toolkit: convert legacy SSPs to OSCAL, validate with Trestle and oscal-cli, FedRAMP Rev 5 and 20x KSI workflows. Claude Code plugin plus portable skills for Cursor, Codex, Gemini, and more.

Install
npx -y skills add ethanolivertroy/compliance-trestle-skills --skill trestle-jinja-templating

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 12 stars12 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Knowledge about Compliance Trestle's Jinja2 templating system for generating compliance documents. Use when users ask about Jinja templates, document generation from OSCAL data, custom trestle Jinja tags (mdsection_include, md_clean_include, md_datestamp), custom filters (as_list, get_party, parties_for_role, diagram_href), SSP document rendering, lookup tables, or bracket formatting.

SKILL.md

9.2 KB, as published. Nobody here has run it

Trestle Jinja Templating

Trestle provides a Jinja2-based templating system (trestle author jinja) for generating compliance documents from OSCAL data. Templates can reference SSPs, profiles, and catalogs to produce formatted markdown or other document formats.

Command Usage

trestle author jinja -i <template_path> -o <output_path> [options]

Custom Jinja Tags

Trestle extends Jinja2 with three custom tags:

mdsection_include

Include a specific section from a markdown file by heading title:

{% mdsection_include "path/to/file.md" "Section Title" heading_level=2 %}
  • heading_level controls which heading level to search for (default: based on document structure)
  • Extracts the section and all content until the next heading of equal or higher level

md_clean_include

Include an entire markdown file, stripping YAML frontmatter:

{% md_clean_include "path/to/file.md" heading_level=2 %}
  • Removes YAML frontmatter (between --- markers)
  • Adjusts heading levels relative to heading_level
  • Useful for composing documents from multiple markdown sources

md_datestamp

Insert a formatted date stamp:

{% md_datestamp format="%Y-%m-%d" newline=True %}
  • format follows Python strftime format strings
  • newline adds a trailing newline (default: True)

Custom Jinja Filters

FilterDescriptionExample
as_listConvert value to a list{{ value | as_list }}
get_defaultGet the default value{{ param | get_default }}
first_or_noneGet first element or None{{ items | first_or_none }}
get_partyGet party by UUID from SSP{{ ssp | get_party(uuid) }}
parties_for_roleGet all parties for a role ID{{ ssp | parties_for_role(role_id) }}
diagram_hrefGet diagram link href{{ diagram | diagram_href }}

Context Objects

When an SSP is provided (--ssp), these objects are available in templates:

VariableTypeDescription
sspSystemSecurityPlanThe full SSP object
catalogCatalogResolved catalog from the SSP's profile
catalog_interfaceCatalogInterfaceUtility for querying catalog controls
control_interfaceControlInterfaceUtility for working with individual controls
control_writerDocsControlWriterWriter for formatting control documentation
ssp_md_writerSSPMarkdownWriterWriter for SSP markdown output

When --docs-profile is used for per-control output:

VariableTypeDescription
profileProfileThe profile being processed
controlControlCurrent control being rendered
group_titlestrTitle of the control's group

Lookup Tables

Provide additional variables via a YAML lookup table (-lut):

# lookup.yaml
system_name: My Federal System
authorization_date: 2024-01-15
fips_level: Moderate
# In template
System Name: {{ system_name }}
Authorization Date: {{ authorization_date }}

Bracket Formatting

The -bf / --bracket-format flag controls how parameter values appear:

FormatExample Output
[.][value]
((.))((value))
Nonevalue (no brackets)

Use -vap and -vnap to prefix values based on assignment status:

  • -vap "Assigned: " — prefix when parameter has a value
  • -vnap "MISSING: " — prefix when parameter has no value

Example Templates

SSP Front Matter Template

---
title: System Security Plan
date: {% md_datestamp format="%B %d, %Y" %}
---

# {{ ssp.system_characteristics.system_name }}

## System Description
{{ ssp.system_characteristics.description }}

## Authorization Boundary
{% mdsection_include "boundary.md" "Authorization Boundary" heading_level=2 %}

## Leveraged Services
{% for leveraged in ssp.system_implementation.leveraged_authorizations %}
- {{ leveraged.title }}
{% endfor %}

Control Documentation Template

# Control: {{ control.id }}

{% for part in control.parts %}
## {{ part.name }}
{{ part.prose }}
{% endfor %}

### Responsible Parties
{% for role in control.responsible_roles %}
- {{ role.role_id }}: {% for party_uuid in role.party_uuids %}{{ ssp | get_party(party_uuid) }}{% endfor %}
{% endfor %}

Assessment and POA&M Report Templates

Assessment data is not directly available as Jinja context objects (unlike SSPs). To use assessment and POA&M data in Jinja templates, pre-extract the data into YAML lookup tables and pass them via -lut.

Assessment Report Template

Prepare a lookup table with extracted assessment data:

# assessment-lookup.yaml
assessment_title: "Annual Security Assessment 2024"
assessment_date: "2024-02-28"
assessor: "Security Assessment Team"
total_controls: 45
satisfied_count: 38
not_satisfied_count: 5
other_count: 2

findings:
  - control_id: "AC-1"
    title: "Outdated Access Control Policy"
    status: "not-satisfied"
    risk_level: "High"
    observation: "Policy last updated 3 years ago"
  - control_id: "AC-2"
    title: "Account Management"
    status: "satisfied"
    risk_level: "N/A"
    observation: "Account management procedures verified"
  - control_id: "SC-7"
    title: "Boundary Protection"
    status: "satisfied"
    risk_level: "N/A"
    observation: "Network boundary controls verified via scan"

Template for an assessment report:

---
title: {{ assessment_title }}
date: {% md_datestamp format="%B %d, %Y" %}
---

# Assessment Report: {{ assessment_title }}

**Assessment Date:** {{ assessment_date }}
**Assessor:** {{ assessor }}

## Summary

| Metric | Count |
|--------|-------|
| Total Controls Assessed | {{ total_controls }} |
| Satisfied | {{ satisfied_count }} |
| Not Satisfied | {{ not_satisfied_count }} |
| Other | {{ other_count }} |

## Findings Summary

| Control | Title | Status | Risk Level |
|---------|-------|--------|------------|
{% for finding in findings -%}
| {{ finding.control_id }} | {{ finding.title }} | {{ finding.status }} | {{ finding.risk_level }} |
{% endfor %}

## Detailed Findings

{% for finding in findings %}
{% if finding.status == "not-satisfied" %}
### {{ finding.control_id }}: {{ finding.title }}

**Status:** {{ finding.status }}
**Risk Level:** {{ finding.risk_level }}
**Observation:** {{ finding.observation }}

{% endif %}
{% endfor %}

Run with:

trestle author jinja -i assessment-report.md.j2 -o assessment-report.md -lut assessment-lookup.yaml

POA&M Status Report Template

Prepare a lookup table with POA&M data:

# poam-lookup.yaml
system_name: "My Federal System"
report_date: "2024-03-15"
total_items: 5
open_items: 3
closed_items: 1
deviation_items: 1

risk_breakdown:
  high: 2
  moderate: 2
  low: 1

poam_items:
  - id: "POAM-001"
    control: "AC-1"
    title: "Outdated Access Control Policy"
    risk_level: "High"
    status: "remediating"
    due_date: "2024-03-31"
    milestones:
      - title: "Draft updated policy"
        due: "2024-03-15"
        status: "complete"
      - title: "Policy approved"
        due: "2024-03-31"
        status: "in-progress"
  - id: "POAM-002"
    control: "AU-2"
    title: "Incomplete Audit Logging"
    risk_level: "High"
    status: "open"
    due_date: "2024-08-31"
    milestones:
      - title: "Phase 1: Core logging"
        due: "2024-04-30"
        status: "pending"

Template for a POA&M status report:

---
title: POA&M Status Report - {{ system_name }}
date: {% md_datestamp format="%B %d, %Y" %}
---

# POA&M Status Report

**System:** {{ system_name }}
**Report Date:** {{ report_date }}

## Summary

| Status | Count |
|--------|-------|
| Open | {{ open_items }} |
| Closed | {{ closed_items }} |
| Deviation/Accepted | {{ deviation_items }} |
| **Total** | **{{ total_items }}** |

## Risk Breakdown

| Risk Level | Count |
|------------|-------|
| High | {{ risk_breakdown.high }} |
| Moderate | {{ risk_breakdown.moderate }} |
| Low | {{ risk_breakdown.low }} |

## Open Items

| ID | Control | Title | Risk | Status | Due Date |
|----|---------|-------|------|--------|----------|
{% for item in poam_items -%}
{% if item.status != "closed" -%}
| {{ item.id }} | {{ item.control }} | {{ item.title }} | {{ item.risk_level }} | {{ item.status }} | {{ item.due_date }} |
{% endif -%}
{% endfor %}

## Milestone Timeline

{% for item in poam_items %}
{% if item.status != "closed" %}
### {{ item.id }}: {{ item.control }} - {{ item.title }}

| Milestone | Due Date | Status |
|-----------|----------|--------|
{% for ms in item.milestones -%}
| {{ ms.title }} | {{ ms.due }} | {{ ms.status }} |
{% endfor %}

{% endif %}
{% endfor %}

Run with:

trestle author jinja -i poam-report.md.j2 -o poam-report.md -lut poam-lookup.yaml

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.