🧱 InfraKit
Spec it. Plan it. Ship it.
spec-kit for IaC, with a multi-persona pipeline. Open-source; works with Claude Code, Codex, Gemini, Copilot, plus any generic agent; ships Crossplane, Terraform, and CloudFormation out of the box.
Table of Contents
- 🤔 What is InfraKit?
- ⚡ Get Started
- 🤖 Supported AI Coding Agents
- 🧰 Supported IaC Platforms
- 🔤 Available Slash Commands
- 📦 InfraKit CLI Reference
- 🧭 The Track System
- 📚 Core Philosophy
- 🌟 Development Phases
- 📁 Examples
- 🔧 Prerequisites
- 📋 Detailed Process
- 🔍 Troubleshooting
- 📖 Learn More
- 💬 Support
- 🙏 Acknowledgements
- 📄 License
🤔 What is InfraKit?
InfraKit is spec-kit for infrastructure-as-code, with a multi-persona pipeline layered on top. Spec-kit pioneered Spec-Driven Development for application code: capture the spec first, then plan, then implement, with every artifact committed to git. InfraKit takes that shape, points it at Crossplane, Terraform, and CloudFormation, and inserts four specialized personas between the spec and the code so that cloud architecture, security compliance, and IaC implementation each get their own dedicated review pass.
Concretely: a Cloud Solutions Engineer persona translates intent into a structured spec. A Cloud Architect presents 2–3 design options with cost/reliability trade-offs. A Cloud Security Engineer flags structural patterns that commonly violate SOC 2, HIPAA, ISO 27001, CIS, and NIST controls before any code is written. An IaC Engineer then generates Crossplane YAML, Terraform HCL, or a CloudFormation template — and a full audit trail (spec, plan, task list, changelog) lands alongside the code in git.
In a hurry? The lighter /infrakit:quick_fix path skips the multi-persona spec ceremony: the IaC Engineer plans your requirement, generates a task list, shows you the plan to approve, then implements (still verifying provider field names, applying required tags, and gating on validation).
A note on compliance: the security review is a heuristic LLM pass that flags common control violations against named frameworks. It is not a substitute for a real audit conducted by qualified humans with evidence collection. Use it as a first-pass guardrail, not as your compliance system of record.
⚡ Get Started
1. Install InfraKit CLI
Choose your preferred installation method:
[!NOTE] The commands below require uv — a fast Python package manager. If you see
command not found: uv, install uv first. Thepipxalternative does not require uv.
# Persistent installation (recommended) — installs the latest release from PyPI
uv tool install infrakit-cli
# Pin a specific release (replace X.Y.Z with the latest from
# https://pypi.org/project/infrakit-cli/ or the Releases page)
uv tool install infrakit-cli==X.Y.Z
# Alternative: pipx
pipx install infrakit-cli
Verify the install:
infrakit version
One-time usage
Run directly without installing:
uvx infrakit-cli init my-infra --ai claude --iac crossplane
[!TIP] Prompts, personas, and templates ship inside the wheel.
infrakit initruns entirely offline — no GitHub tokens, no per-agent release zips, no network calls. Per-agent rendering (Claude / Gemini / Copilot / etc.) happens on your machine at init time.
2. Initialize your project
# New directory
infrakit init my-infra --ai claude --iac crossplane
# Existing directory
infrakit init --here --ai claude --iac terraform
In interactive sessions you'll be prompted for the AI agent and IaC tool. In CI or piped runs, pass --ai and --iac explicitly.
3. Configure project standards
Run your AI coding agent in the project directory. Use the /infrakit:setup command to capture your project's governing principles — these become the constraints every subsequent step must honour.
/infrakit:setup AWS multi-account platform; SOC 2 + PCI-DSS in scope; encryption at rest mandatory; no public network access in prod
This generates .infrakit/context.md, .infrakit/coding-style.md, and .infrakit/tagging-standard.md.
4. Specify the resource
Describe what you want, not how. The Solutions Engineer iterates until the requirements are clear, then hands off to Architect and Security Engineer reviews.
Crossplane:
/infrakit:new_composition A PostgreSQL Crossplane composition wrapping AWS RDS. Multi-AZ in prod, Multi-AZ defaults to false elsewhere. Per-instance customer-managed KMS key. No public access ever. Connection details published to a Kubernetes Secret in the claimer's namespace.
Terraform:
/infrakit:create_terraform_code An AWS S3 bucket module. Encryption with a customer-managed KMS key, all four block_public_* flags set, TLS-only access via bucket policy, lifecycle on non-current versions, optional cross-region replication gated to prod.
CloudFormation:
/infrakit:create_cloudformation_code An RDS PostgreSQL template. StorageEncrypted with a customer-managed KMS key, PubliclyAccessible false always, Multi-AZ in prod via a Condition, master password supplied as a NoEcho parameter resolved from Secrets Manager, endpoint exported for cross-stack use.
The four-persona pipeline runs end-to-end. Output: a confirmed spec.md in .infrakit_tracks/tracks/<track-name>/.
In a hurry?
/infrakit:quick_fix <requirement> [directory]runs a lighter loop — the IaC Engineer plans your requirement, generates a task list, shows youplan.md+tasks.mdto approve, then implements (verifying field names, applying tags, gating on validation). It skips only the multi-persona spec/architect/security review. Reach for the full pipeline above when the change is compliance-sensitive or a new design with real trade-offs.
5. Plan the implementation
/infrakit:plan <track-name>
The IaC Engineer verifies provider API field names against official docs (never guessing), designs parameter → argument mappings, writes plan.md, and auto-generates tasks.md — an ordered, checkbox task list.
6. Execute the implementation
/infrakit:implement <track-name>
The IaC Engineer works through each task in tasks.md, marks them complete, and writes the post-implementation artifacts (.infrakit_context.md, .infrakit_changelog.md, and a regenerated README.md) alongside the code.
7. Review
/infrakit:review <resource-directory>
Reviews generated code against coding-style.md and tagging-standard.md. Findings are categorized CRITICAL / HIGH / MEDIUM / LOW; the engineer offers to apply fixes inline.
For a complete worked walkthrough, see examples/.
🤖 Supported AI Coding Agents
InfraKit installs slash commands (or skills via --ai-skills) into any of these five agents:
| Agent | Flag | Subagents | Notes |
|---|---|---|---|
| Claude Code | --ai claude |
✅ Yes | Recommended — uses the Task tool to isolate persona review phases. |
| Codex CLI | --ai codex |
— | |
| Gemini CLI | --ai gemini |
— | Commands rendered as TOML. |
| GitHub Copilot | --ai copilot |
— | Auto-emits prompt + agent file pair; configures VS Code settings. |
| Generic — bring your own agent | --ai generic |
— | Use with --ai-commands-dir <path>. |
The "Subagents" column flags whether the agent has a built-in primitive (Claude Code's Task tool) that InfraKit's multi-persona commands can delegate to. With native subagents, the Cloud Architect and Cloud Security Engineer review phases run in isolated context windows — the architect's reasoning never sees the security review's reasoning, and vice versa. On agents without subagents, the same review prompts run inline; the context boundaries are explicit but not enforced.
If you encounter issues with one of the supported agents, please open an issue. Other agents were dropped in v0.2 because the maintenance surface (per-agent layout, MCP install paths, command-format quirks, untested subagent semantics) was unmaintainable; if you want first-class support for another agent, please open an issue describing the use case.
🧰 Supported IaC Platforms
| Platform | Status | Output | Resource Term |
|---|---|---|---|
| Crossplane | ✅ Supported | YAML | Composition |
| Terraform | ✅ Supported | HCL | Module |
| AWS CloudFormation | ✅ Supported | YAML | Template |
| OpenTofu | 🗺️ Roadmap | — | — |
| Pulumi | 🗺️ Roadmap | — | — |
🔤 Available Slash Commands
After running infrakit init, your AI coding agent has access to these slash commands, prefixed /infrakit:. With --ai-skills, the same commands install as agent skills.
Core Commands
Essential commands for the spec-driven workflow:
| Command | Description |
|---|---|
/infrakit:setup |
Capture project context, coding standards, and tagging requirements |
/infrakit:setup-coding-style |
Update or replace project coding-style standards |
/infrakit:new_composition |
(Crossplane) Solutions → Architect → Security → spec workflow for a new XR/Composition |
/infrakit:create_terraform_code |
(Terraform) Solutions → Architect → Security → spec workflow for a new module |
/infrakit:create_cloudformation_code |
(CloudFormation) Solutions → Architect → Security → spec workflow for a new template |
/infrakit:plan |
Generate the implementation plan and auto-generate tasks.md |
/infrakit:implement |
Execute tasks from tasks.md, mark complete, write context / changelog / README |
/infrakit:review |
Review generated code against coding standards and tagging |
/infrakit:quick_fix |
Lighter path: requirement → IaC Engineer plans, generates tasks, you review, then implements |
Brownfield Commands
For updating resources that already exist:
| Command | Description |
|---|---|
/infrakit:update_composition |
(Crossplane) Brownfield scan → context review → solutioning → updated spec |
/infrakit:update_terraform_code |
(Terraform) Brownfield scan → context review → solutioning → updated spec |
/infrakit:update_cloudformation_code |
(CloudFormation) Brownfield scan → context review → solutioning → updated spec |
Quality & Review Commands
Optional commands for cross-artifact validation:
| Command | Description |
|---|---|
/infrakit:analyze |
Cross-artifact consistency check — verifies spec, plan, and code are aligned |
/infrakit:architect-review |
Cloud Architect review for architecture correctness, reliability, and cost |
/infrakit:security-review |
Cloud Security Engineer compliance review (SOC 2, HIPAA, ISO 27001, CIS, NIST, PCI-DSS) |
/infrakit:status |
Dashboard showing all tracks and their current status |
📦 InfraKit CLI Reference
| Command | Description |
|---|---|
infrakit init |
Initialize a new InfraKit project — renders the per-agent layout from bundled prompts |
infrakit check |
Check installed tools (git, agent CLIs, plus per-IaC tools: kubectl, terraform, aws, cfn-lint, …) |
infrakit mcp |
Install a pre-defined MCP server recipe into your agent's MCP config |
infrakit version |
Display CLI version and system information |
infrakit init options
| Option | Type | Description |
|---|---|---|
<project-name> |
Positional | Name for your new project directory (omit with --here) |
--here |
Flag | Initialize in the current directory instead of a new subdirectory |
--ai |
Choice | AI assistant — see Supported AI Coding Agents |
--ai-commands-dir |
Path | Command files directory (required with --ai generic) |
--iac |
Choice | IaC tool: crossplane, terraform, or cloudformation |
--script |
Choice | Script type: sh (default) or ps (PowerShell) |
--ignore-agent-tools |
Flag | Skip AI agent tool availability checks |
--no-git |
Flag | Skip git init |
--force |
Flag | Skip confirmation when initializing in a non-empty directory |
--debug |
Flag | Verbose diagnostic output |
--ai-skills |
Flag | Install prompts as agent skills instead of slash commands |
Examples
# New project with Claude Code and Crossplane
infrakit init my-infra --ai claude --iac crossplane
# New project with Claude Code and Terraform
infrakit init my-infra --ai claude --iac terraform
# New project with Claude Code and AWS CloudFormation
infrakit init my-infra --ai claude --iac cloudformation
# Initialize in the current directory
infrakit init --here --ai claude --iac crossplane
# Force-merge into an existing non-empty directory
infrakit init --here --force --ai claude --iac crossplane
# Skip git init (useful in CI)
infrakit init my-infra --ai gemini --iac crossplane --no-git
# Bring your own agent
infrakit init my-infra --ai generic --ai-commands-dir .myagent/commands/ --iac crossplane
# Check system prerequisites
infrakit check
# Install an MCP server
infrakit mcp
🧭 The Track System
Every resource change gets its own track — a versioned directory under .infrakit_tracks/tracks/<track-name>/ that holds spec, plan, task list, and per-persona review artifacts. Multiple tracks run in parallel. Every step is committed alongside the code, giving you a permanent audit trail of why each resource exists and how its design was approved.
.infrakit/ # Project-wide standards (read by every command)
├── config.yaml # iac_tool, ai_assistant, resource_term
├── context.md # Cloud provider, naming, environment policies
├── coding-style.md # Mandatory coding standards
├── tagging-standard.md # Required resource tags
├── memory/ # Project memory for AI agents
└── agent_personas/ # Persona definitions
.infrakit_tracks/
├── tracks.md # Registry of all tracks and their status
└── tracks/
└── postgres-database-20260401-120000/
├── spec.md # Requirements, parameters, outputs, security
├── plan.md # Implementation plan
├── tasks.md # Auto-generated ordered task list
├── analyze.md # /infrakit:analyze output
├── architect-review.md # /infrakit:architect-review output
├── security-review.md # /infrakit:security-review output
└── review.md # /infrakit:review output
Per-resource artifacts written by /infrakit:implement (committed alongside the resource):
<resource-directory>/
├── .infrakit_context.md # Resource interface: parameters/variables, outputs, resources
├── .infrakit_changelog.md # Append-only structured change history
└── README.md # Human-readable usage + interface contract
The generated code itself is the machine-readable contract — the XRD (
definition.yaml) for Crossplane,variables.tf/outputs.tf/versions.tffor Terraform,template.yamlfor CloudFormation — and theREADME.mdis the human-readable one. InfraKit no longer writes a separate*_contract.mdfile.
Track status lifecycle
| Status | Meaning | Next step |
|---|---|---|
🔵 initializing |
Track created, spec in progress | Complete requirements with Solutions Engineer |
📝 spec-generated |
Spec confirmed by all personas | /infrakit:plan <track-name> |
📋 planned |
Plan and task list generated | /infrakit:implement <track-name> |
⚙️ in-progress |
Implementation underway | Continue /infrakit:implement |
✅ done |
Implementation complete and reviewed | Merge, close track |
❌ blocked |
Blocked — needs attention | Resolve blocker, update track status |
📚 Core Philosophy
InfraKit borrows its core philosophy from spec-kit — capture intent in a structured spec before writing code — and layers four IaC-specific ideas on top:
- Standards first — cloud provider standards, naming, tagging, compliance, and security defaults are captured before writing any code (via
/infrakit:setup). Every downstream artifact must honour them. - Multi-persona refinement — separate the requirements, architecture, security, and implementation roles into distinct personas with distinct vocabularies. The hypothesis is that one model wearing four hats produces sharper output than one model trying to balance all four at once. (This is an empirical claim we are still validating; see the acknowledgements note.)
- Provider-verified field names — the IaC Engineer is prompted to read official provider docs before writing anything. Hallucinated
aws_db_instanceargument names that look right but cause apply failures are one of the most common reasons teams stop trusting AI for IaC. - Full audit trail in git — spec, plan, task list, per-persona reviews, and the final code all land together. Every architectural decision and every compliance waiver is traceable from the resource back to a human approval.
🌟 Development Phases
| Phase | Focus | Key Activities |
|---|---|---|
| Greenfield Development | Create new resources from scratch |
|
| Iterative Enhancement ("Brownfield") | Update existing resources |
|
| Continuous Compliance | Audit and enforce on every change |
|
📁 Examples
Three complete, end-to-end walkthroughs showing every file InfraKit produces:
| Example | IaC Tool | Scenario |
|---|---|---|
examples/terraform/ |
Terraform | AWS S3 secure-bucket module — KMS, public-access blocked, TLS-only, lifecycle, optional CRR |
examples/crossplane/ |
Crossplane | XPostgreSQLInstance wrapping AWS RDS via provider-aws-rds with per-instance KMS |
examples/cloudformation/ |
CloudFormation | AWS S3 secure-bucket template — KMS, public access blocked, TLS-only, lifecycle, versioning |
Each example contains the .infrakit/ config, a single track under .infrakit_tracks/tracks/, and the final deliverable (the .tf module, Composition YAML, or CloudFormation template.yaml).
🔧 Prerequisites
- Linux / macOS / Windows
- One of the supported AI coding agents
- uv for package management (recommended) or pipx for persistent installation
- Python 3.11+
- Git
- For Crossplane: kubectl plus a Crossplane-enabled cluster (or kind for local dev)
- For Terraform: Terraform or OpenTofu
- For CloudFormation: the AWS CLI and (recommended) cfn-lint for local validation
📋 Detailed Process
Click to expand the full spec-driven workflow walkthrough
Step 0 — Bootstrap the project
infrakit init my-infra --ai claude --iac crossplane
cd my-infra
You'll see your project populated with:
.claude/commands/(or.gemini/commands/,.github/agents/, etc. depending on--ai).infrakit/—config.yaml,context.mdplaceholder,coding-style.mdplaceholder,tagging-standard.mdplaceholder, generic and IaC-specific personas.infrakit_tracks/tracks.md— empty registry.vscode/settings.json(Copilot only)
Launch your AI agent. Use the /infrakit:setup command to fill in your project context.
Step 1 — Establish project standards
/infrakit:setup
The Solutions Engineer asks one question at a time:
- Cloud provider(s) and regions
- Naming convention pattern
- Environment list (dev / staging / prod / etc.)
- Tagging requirements (which tags are required on every resource and where their values come from)
- Security baseline (encryption-at-rest defaults, public-access defaults, IAM rules)
- Compliance frameworks in scope
- Architecture decisions already locked in (IaC tool version, GitOps engine, state backend)
The output lands in .infrakit/context.md and .infrakit/tagging-standard.md. Then:
/infrakit:setup-coding-style
…populates .infrakit/coding-style.md with your project's coding standards (file layout, naming, versioning policy, validation patterns, provider config, backend config, etc.).
[!IMPORTANT] Be explicit about what standards apply and why. Every downstream command reads these files; vague answers here produce vague code.
Step 2 — Specify the resource
For Crossplane:
/infrakit:new_composition An AWS RDS PostgreSQL composition. Allow callers to set instanceClass, storageGB, multiAZ override. Default Multi-AZ to true in prod. Per-instance customer-managed KMS key. publicly_accessible=false always. Connection details published as a Kubernetes Secret in the claim's namespace.
For Terraform:
/infrakit:create_terraform_code An AWS S3 secure bucket module. KMS encryption with a customer-managed key. All four block_public_* flags set. TLS-only via aws:SecureTransport deny policy. Optional cross-region replication gated to prod only.
The Solutions Engineer iterates until requirements are clear (it will ask clarifying questions before writing anything). Then the Architect presents 2–3 named design options with cost / reliability / complexity trade-offs. Finally the Security Engineer asks which compliance frameworks apply and audits the spec against them.
Output: .infrakit_tracks/tracks/<track-name>/spec.md, with the track registered at status 📝 spec-generated.
Step 3 — Plan
/infrakit:plan <track-name>
The IaC Engineer:
- Verifies the API versions and field names of every provider resource (against
doc.crds.devfor Crossplane orregistry.terraform.iofor Terraform) - Designs the parameter → resource argument mapping table
- Designs the output → attribute mapping table
- Writes
plan.md - Auto-generates
tasks.md— an ordered, checkbox task list for each implementation phase
Track status → 📋 planned.
Step 4 — Implement
/infrakit:implement <track-name>
The IaC Engineer:
- Validates that constitution, spec, plan, and tasks are all in place
- Walks
tasks.mdtop-to-bottom, marking each- [ ]→- [x]as it goes - Writes the actual
.tfor YAML files into the target directory - After all tasks complete, writes three post-implementation artifacts:
.infrakit_context.md— resource interface (parameters/variables, outputs, resources provisioned).infrakit_changelog.md— append-only structured change historyREADME.md— regenerated from the code as the human-readable interface contract
Track status → ✅ done.
Step 5 — Cross-artifact analysis
Run before merging:
/infrakit:analyze <track-name>
The Cloud Solutions Engineer cross-checks spec ↔ plan ↔ generated code for drift. Findings categorized by severity. No automatic edits — the agent presents findings and asks you which to apply.
/infrakit:architect-review <track-name>
Architecture quality gate: reliability, cost, completeness, environment-aware checks.
/infrakit:security-review <track-name>
Compliance audit against the frameworks chosen in step 2. Findings against each control are tabulated; CRITICAL/HIGH gaps require either fixes or documented waivers.
Step 6 — Code review
/infrakit:review <resource-directory>
Reviews the generated HCL or YAML against coding-style.md and tagging-standard.md. Verdict: APPROVED / APPROVED WITH NOTES / NEEDS FIXES. Agent offers to apply fixes inline.
Iterating
For brownfield work (updating an existing resource), use /infrakit:update_composition, /infrakit:update_terraform_code, or /infrakit:update_cloudformation_code instead of the new_* / create_* commands. These first scan the existing code into .infrakit_context.md (reconstructing it from the code if absent), present it for your review, then run the spec → plan → implement workflow against the updated requirements.
🔍 Troubleshooting
Corporate proxy / self-signed certificates
Templates ship inside the InfraKit wheel, so InfraKit makes no network calls at all — infrakit init, check, mcp, and version all run entirely offline. Corporate proxies and self-signed certificates are a non-issue; nothing in the CLI reaches out to the network.
tasks.md not found when running /infrakit:implement
tasks.md is auto-generated by /infrakit:plan after you accept the plan. If it is missing, re-run /infrakit:plan <track-name>.
Track directory not found
Tracks live under .infrakit_tracks/tracks/<track-name>/. If you initialized with an older version of InfraKit (< 0.2.0), your tracks may be under .infrakit/tracks/. Move them:
mkdir -p .infrakit_tracks/tracks
mv .infrakit/tracks/* .infrakit_tracks/tracks/
mv .infrakit/tracks.md .infrakit_tracks/tracks.md
📖 Learn More
| Resource | Description |
|---|---|
| Quick Start Guide | End-to-end Crossplane workflow walkthrough |
| Installation Guide | Detailed installation, upgrades, and corporate-proxy setup |
| Upgrade Guide | How to upgrade the CLI and update project template files |
| Examples | Full Terraform, Crossplane, and CloudFormation walkthroughs |
| CHANGELOG | Full version history and breaking changes |
| CONTRIBUTING | How to contribute to InfraKit |
💬 Support
For bug reports, feature requests, or questions, please open a GitHub issue.
🙏 Acknowledgements
InfraKit's workflow shape is heavily influenced by GitHub Spec Kit and the wider Spec-Driven Development community. The multi-persona pipeline is original to InfraKit and grew out of running real Crossplane and Terraform migrations where a single "AI generates code" prompt was never enough.
📄 License
This project is licensed under the terms of the MIT open source license. See the LICENSE file for the full terms.
Metadata
Release files for infrakit-cli 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| infrakit_cli-1.0.0.tar.gz | 238.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| infrakit_cli-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 439.6 kB
Release files / infrakit_cli-1.0.0.tar.gz
| Download URL | infrakit_cli-1.0.0.tar.gz |
|---|---|
| Size | 238.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3ebf9fb5f1adef57709f56bc72c1a282886db5de89a795ca999bdc1e014c5a6d
|
|
BLAKE2b-256 checksum How to use checksums |
4321fe54e7e98c365d5aea37dbf985b4d9fa1bb03e27ca22f754f28dfd032c11
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 31, 2026.
Transparency logRelease files / infrakit_cli-1.0.0-py3-none-any.whl
| Download URL | infrakit_cli-1.0.0-py3-none-any.whl |
|---|---|
| Size | 201.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
0c868e39223f4e385a284e43d00332e51801fa5c3ef3a291812dd4aa4a63bae4
|
|
BLAKE2b-256 checksum How to use checksums |
34b271848ad372b4131d5b448c7fca993d405d3798305127a29305454b294ea6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.13
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on May 31, 2026.
Transparency log