ansible-plaibook
AI-powered code review, running as an unattended Ansible playbook rather than a chat. plai review puts independent lenses on a diff, then scores the findings that are still standing. The score comes from that list, not from the model's own grade. Same command from a terminal, a git hook, or an AAP job template.
pipx install plaibook
plai review
No arguments reviews HEAD in the current directory. plai review org/repo/123 is a pull request or merge request. plai update upgrades the install that just ran.
The PyPI name is plaibook. plai was already taken, so the two commands are one program. Homebrew and Debian will not let you pip install into the system Python (PEP 668). A virtualenv you already manage can pip install plaibook. The first run puts the provider collections in ~/.cache/ansible-plaibook/collections and does not touch ~/.ansible.
A quiet run prints the verdict, the score, and each Critical or Major finding with file:line and a short why. Minor and nit stay as counts. The footer is the cost and this run's last_run.<run_id>.json. -v is the Ansible task list. --json is what another program should parse. Commit review, and how to read a run, are in Getting started. The CLI's own notes are in plaibook/README.md.
Collections
The model calls and the sandbox are separate collections. Plaibook pins them and composes them. They do not import each other.
| Collection | Repository | Role |
|---|---|---|
aknochow.claude |
ansible-claude | Claude, including the Agent SDK |
aknochow.gemini |
ansible-gemini | Gemini |
aknochow.openai |
ansible-openai | OpenAI-compatible chat |
aknochow.cursor |
ansible-cursor | Cursor agent |
aknochow.openshell |
ansible-openshell | Sandbox lifecycle and the SSH proxy |
OpenShell does not know which provider is in use. A provider collection does not know OpenShell exists. Sandbox lifecycle is delegate_to. The review role never imports it. How those calls are split is in Sandboxes and LLM calls.
The SHAs and SDK versions are not interchangeable. The map, and the order a bump has to follow, is docs/dependency-map.md.
Ansible
review.yml already runs as an AAP job template against real merge requests. You get the RBAC, credentials, scheduling, and audit log you already use for everything else. The image and the tag to pin are under Running it in AAP.
Every step is a named task. ansible.posix.profile_tasks is on, and each review records cost and tokens per call. Scores are recomputed from the findings that remain. A lens can talk itself out of one in prose. The number moves when the finding is actually dropped. There is no resident agent process. You pay for the calls a run makes.
The playbook uses the Ansible tools that already exist:
ansible-lintruns in the pre-commit hook and in CI. The profile in.ansible-lintismin.ansible-builderbuilds the execution environment. See Execution environment.ansible-galaxyinstalls the collections fromcollections-requirements.yml.ansible-navigatorruns the playbook in that image.- AWX and Ansible Automation Platform run the job.
ansible-runneris what the platform uses under the job. ansible-docis how the collections document their modules.
The rest of the docs are the index. People changing this repo start at CONTRIBUTING. How the stages fit together is Architecture.
Running it in AAP
execution-environment.yml builds ghcr.io/aknochow/plaibook-ee, a
multi-arch (linux/amd64 and linux/arm64) execution environment. It
carries every collection pinned in collections-requirements.yml, the
Python dependencies those collections need, and gh/glab for PR/MR
API access. A pin bump on main rebuilds the image. This playbook has
already run as a real AAP Job Template against real MRs.
Use a version tag for AAP Job Templates. :<version> matches a
plaibook release (:0.1.29 is the image for tag v0.1.29). :main
and :latest follow main and can be ahead of the newest PyPI
release.
OpenShell ssh_proxy.py and certs are not in the image. Supply them
at job-run time if a review needs them.
Verify a published tag before using it:
cosign verify --certificate-oidc-issuer https://token.actions.githubusercontent.com --certificate-identity-regexp '^https://github.com/aknochow/ansible-plaibook/\.github/workflows/ee-publish\.yml@refs/(heads/main|tags/v.+)$' ghcr.io/aknochow/plaibook-ee:0.1.29
To build and host your own, from a clean checkout. --squash all is the same flag CI uses. The build process, the layer count, and why new does not fix a local Podman mount are in Execution environment.
ansible-builder build --squash all -t <your-registry>/plaibook-ee:latest -f execution-environment.yml
podman push <your-registry>/plaibook-ee:latest
Credentials (GitHub/GitLab tokens, OpenShell mTLS) are injected via AAP credentials at job-run time, never baked into the image.
The image includes aknochow.cursor. review.yml loads that
collection only when agent_family=cursor starts the sidecar. Rebuild
when collections-requirements.yml or execution-environment.yml
changes. A Vertex-only parse failure is a playbook bug, not a missing
collection.
Metadata
Release files for plaibook 0.1.29
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| plaibook-0.1.29.tar.gz | 530.0 kB | With provenance | Details for plaibook-0.1.29.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| plaibook-0.1.29-py3-none-any.whl | Python 3 | none | any | Details for plaibook-0.1.29-py3-none-any.whl |
Total release size: 1.1 MB
Release files / plaibook-0.1.29.tar.gz
| Download URL | plaibook-0.1.29.tar.gz |
|---|---|
| Size | 530.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f40ad2f97bfc5fc2461dd10104985fd3e9f9d4f66639c14f0be8e07cae5bf044
|
|
BLAKE2b-256 checksum How to use checksums |
63f32a694a07d9e81e2163711e5f36ea99fc2422d363837ece049e9ee9d9b44c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 31, 2026.
Transparency logRelease files / plaibook-0.1.29-py3-none-any.whl
| Download URL | plaibook-0.1.29-py3-none-any.whl |
|---|---|
| Size | 576.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9fead169c3a1e894c216ae5572199c264dab4722e7d778feed787356aa63fc5e
|
|
BLAKE2b-256 checksum How to use checksums |
c59b33e51eb494f787833f9388f81f319b8854bde9488aa806d68adee66d4a54
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
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 Oct 31, 2026.
Transparency logSecurity for plaibook 0.1.29
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for plaibook-0.1.29.tar.gz
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 Oct 31, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.