License. rcdo is free software under the GNU General Public License, version 3 or (at your option) any later version. Modified versions you distribute must be released under the same terms, with their source.
What it is
rcdo is a command-line toolkit for reviewing infrastructure changes before they cause outages. It is designed by a visually impaired operator for blind and low-vision DevOps engineers who use screen readers, braille displays, magnification or large print. Tools such as Terraform, OpenTofu, Ansible, the AWS CLI and gcloud produce long, dense and often colour-coded output. rcdo reads that output, or the structured JSON behind it, and reports what matters first: severity, resource, action, environment and reason.
It works on both sides of a change. Before a change, commands such as prebuild, tofu-check and ansible-check read a saved plan or playbook and say what would be created, changed or deleted. After a change, commands such as receipt-review, ansible-watch and error-explain read what actually ran and what failed. Findings pass through the same policy and reporting layer, so every command produces the same kind of result.
The design follows a few rules stated in the README:
- Plain text is the primary interface. Colour is optional and never the only signal.
- Output has speech and 40-column braille layouts, adjustable line width and no reliance on visual tables.
- It is offline-first, low-dependency and works with ordinary files and pipes.
- It starts read-only and advisory. Any write needs an explicit flag and a preview.
- A partial review is reported as incomplete, never as clean.
What it is not. The checks are conservative guardrails, not proof that a deployment is safe. The README describes the project as an early-stage, "work-ready beta core": each employer must validate its own credentials, schemas, policies and deployment adapters before production use.
Requirements
- Go 1.24 or later to build (
go.moddeclaresgo 1.24.0;.tool-versionspinsgolang 1.24.6). make, for the documented build and install targets.- The repository does not name supported operating systems. The Makefile installs with symlinks, which assumes a Unix-like system.
Most commands read files you already have and need nothing else. Some commands call an external tool, and only those commands need it:
| External tool | Used by |
|---|---|
tofu or terraform | tofu-check --plan (converts a saved plan with show -json) and iac-validate --native |
| Ansible | The optional callback plugin that records events for ansible-watch; ansible-inventory --list output for ansible-scope. rcdo never launches Ansible itself. |
AWS CLI, gcloud, az | Opt-in live identity and inventory collection (cloud-context-check --collect, collect, context-acquire --native) |
spacectl | Live run lookup in spacelift-check and spacelift-watch |
GitHub CLI (gh) | pr-manager collection and --execute |
OPA 1.x (opa) | rego-check, rego-test, rego-diff |
Pandoc, Poppler pdftotext | to-markdown for DOCX and PDF input |
imgsee, pdfsee (from shell2see/) | see, which reads image metadata and bounded PDF text |
| Python 3 | The practice scripts in scripts/, the Ansible callback and the workflow integration scripts |
Run rcdo doctor --sample after building to see which of these it finds on your system.
Build and install
There is no packaged release or tag yet. The quickest route installs the rcdo binary from the default branch with Go:
go install github.com/afterdarksys/rcdo/cmd/rcdo@main
rcdo --versionThat installs only rcdo; run each command as rcdo COMMAND. To verify the build and get the per-command symlinks, build from a clone instead:
git clone https://github.com/afterdarksys/rcdo.git
cd rcdo
make verify
make build
./dist/rcdo --versionmake verify runs go test ./... and go vet ./.... make build creates dist/rcdo and a symlink in dist/ for each command name, so ./dist/rcdo tofu-check and ./dist/tofu-check are the same. The version line is rcdo 1.3.0-beta.1.
Install for one user without administrator access, then make sure $HOME/.local/bin is on PATH:
make install PREFIX="$HOME/.local"Without PREFIX, make install installs to /usr/local/bin. The install target also creates every command-name symlink next to rcdo. New scripts should call rcdo COMMAND [options]; git-tools and git-diff-walker remain only as compatibility names.
Optional user defaults live in a configuration file:
rcdo config init
rcdo config pathQuick start
Try it without credentials
The beta demo uses only the files in examples/. It does not call AWS, Terraform, OpenTofu, Ansible or an AI provider.
./dist/hcl2aws --input examples/decompose-aws.tf
./dist/hcl2aws --input examples/decompose-aws.tf --step 1
rcdo config-explain --input examples/policy.json
rcdo doctor --samplehcl2aws prints a dependency-ordered manual runbook with Execution: NOT RUN in its header. The example contains a placeholder AMI, so the result is INCOMPLETE rather than falsely ready. config-explain reads the JSON one labelled path at a time.
Review a change before applying it
tofu plan -out=review.tfplan
rcdo tofu-check --plan review.tfplan --environment production --format json > tofu-review.json
rcdo review-brief --input tofu-review.json --width 40
git diff | rcdo diff-walk --summary-onlytofu-check flags deletes, replacements, stateful resources, IAM and policy updates, and common public-access indicators. review-brief reduces a report to result, severity, title, target and next action at the width you choose. diff-walk reads a unified diff one change at a time without running Git.
See what a plan and a playbook would do
terraform show -json review.tfplan > plan.json
rcdo prebuild --plan plan.json --playbook site.yml --color=neverprebuild lists the create, update, delete and replace lines from a saved Terraform or OpenTofu plan and the tasks from the playbook. Nothing is applied. With --color=auto it colours a terminal only; the class label such as [vm] is always in the text.
Start of a shift
rcdo context --input snapshot.json --expect work.yaml --format json > context.json
rcdo tofu-check --input plan.json --format json > plan.json.report
rcdo shift --report context.json --report plan.json.report --layout speech --change-id CHG-42
rcdo shift --report context.json --report plan.json.report --format ticket --change-id CHG-42shift reads reports you already have and says who they claim you are, the single highest-severity blocker, the first thing that was not proven, and one next command. Layouts are plain, speech and braille (40 columns by default). --format ticket writes a paragraph for a change ticket; it is not approval to deploy.
Core concepts
Findings and status
Every checker uses one output contract, defined in the finding/ package and specs/finding-format.md. A finding has a stable ID, severity, resource, action, environment, evidence, confidence and remediation. A report has one overall status, and review commands exit with a matching code:
| Status | Exit code | Meaning |
|---|---|---|
CLEAN | 0 | No findings, or a successful operation |
REVIEW | 10 | Findings need review |
BLOCKED | 20 | High or critical findings block the change |
INCOMPLETE | 30 | Evidence is missing, stale or invalid |
| (error) | 2 | Invalid arguments or input |
Review commands accept --format text, json, github (Actions annotations) and sarif (SARIF 2.1.0), and --width with a minimum of 40. Invalid findings are returned as errors rather than shown as a completed review.
The policy layer
Findings can be shaped by several kinds of policy, all optional:
- Suppressions:
--policy FILEtakes a JSON file of suppressions, each with an owner, a reason and an expiry date. Seeexamples/policy.json. - Repository policy:
.rcdo/policy.yamlassigns owners and severities to critical paths, requires companion changes such as runbooks, and rejects repository-specific content. Seeexamples/repository-policy.yaml; it is checked byrepo-policy-checkandreview. - Operational pack:
ops-policy-checkhas built-in rules for public CIDRs, wildcard permissions, disabled encryption or deletion protection, and privileged workloads. - Rego:
rego-check,rego-test,rego-diffandpolicy-reviewrun your own Rego policies through a local OPA. Starter policies are inexamples/rego/. - Plugins: executables in any language, registered in configuration and returning the standard report. Plugin support is off until you enable it globally and per plugin.
Required coverage
deploy-review and review-change combine named reports from the pull request, Actions, OpenTofu, Spacelift, Ansible, cloud context and other sources. You declare which components are required. A missing or invalid required report makes the combined review INCOMPLETE.
Reading and resuming
review-session saves a report and walks it in severity order with next, status, bookmarks, notes and acknowledge. Acknowledging records that a finding was read; it does not clear a blocker. Report and artifact fingerprints are rechecked on resume, and a changed source makes the session stale (exit 30). Similar persistent navigation exists for configuration (config-walk), state (state-walk), Markdown (markdown-view), runbooks and incidents. handoff writes a summary that keeps unresolved blockers.
Guarded edits
config-set and config-remove edit JSON, YAML, TOML and HCL by complete path. By default they print a redacted preview. They write only with --write --expect-sha256 HASH, using the hash from the preview, so a file that changed after you reviewed it is not overwritten.
diffwalk
The diffwalk/ package backs rcdo diff-walk. It reads a unified diff from standard input or --input, and supports a summary, one-based file and hunk selection, case-insensitive search and JSON output. It never runs Git or changes a repository. Optional colour and persistent reviewed-item tracking are planned.
shell2see
shell2see/ is a small, separate set of utilities with its own Makefile: textsee (Go word frequencies), imgsee (Python and Pillow image metadata and ASCII previews), pdfsee (PDF metadata, text and embedded images through Poppler) and pdfgrep (Bash search across PDFs). rcdo see calls imgsee and pdfsee. It does not describe what a picture shows, and it does not perform OCR.
Commands
The repository has three programs under cmd/:
| Program | Purpose |
|---|---|
cmd/rcdo | The main binary. It dispatches on its first argument, or on the name it was invoked as, so each symlink runs one command. |
cmd/git-tools | Compatibility name for the same command suite. |
cmd/git-diff-walker | Compatibility name for diff-walk. |
rcdo help lists 85 commands. They are grouped here by area. Run rcdo COMMAND --help for each command's options, printed one labelled option at a time.
| Area | Commands |
|---|---|
| Shift brief and reading | shift, report-read, review-brief, review-session, handoff, markdown-view, to-markdown, see, log-read |
| Terraform and OpenTofu | prebuild, tofu-check, plan-explain, plan-diff, iac-validate, iac-config-check, iac-context, state-walk, command-gen |
| Decomposition into manual runbooks | decompose, hcl2aws, hcl2ali, ansible2aws, ansible2ali |
| Ansible and Terraform-to-Ansible workflows | ansible-check, ansible-scope, ansible-watch, workflow-check, workflow-trace, workflow-collect |
| Spacelift | spacelift-check, spacelift-runs, spacelift-diff, spacelift-watch |
| Cloud identity and inventory | context, context-acquire, context-summary, cloud-context-check, collect, changes, resource-walk, fleet-check, kube-explain, network-check |
| Permissions and service comparison | permission-check, permission-diff, service-map, service-compare, service-export |
| Git, pull requests and GitHub Actions | review (also git-review), diff-walk, git-danger-check, git-isimportant-check, git-update-json, gha-tool, pr-manager, repo-policy-check |
| Policy and combined review | ops-policy-check, rego-check, rego-test, rego-diff, policy-review, deploy-review, review-change, evidence-pack |
| After a run | receipt-review, jsonprobe-check, error-explain, watch, monitor, audit |
| Structured configuration | config-explain, config-diff, config-walk, config-set, config-remove |
| Operations and incidents | runbook, runbook-check, incident, tasks |
| Setup and acceptance | config, plugin, doctor, pilot, a11y-output-check, ai-assist |
ai-assist sends bounded, redacted input to a configured OpenAI, Anthropic or OpenRouter model only when the --ai flag is given. Its suggestions never write files. No other command needs AI credentials.
The README describes each command with examples, and the guides in docs/ cover the larger workflows.
Integrations
Terraform and OpenTofu
tofu-check reads show -json plan output, or converts a saved plan with --plan and --engine tofu|terraform. plan-explain covers replacement order, unknown and sensitive values, moves and imports, outputs and security changes. plan-diff compares a reviewed plan with a new one. See docs/spacelift-iac.md.
Ansible
ansible-check parses playbook YAML for broad host patterns, shell use, ignored failures, possible plaintext credentials, uncontrolled upgrades and always-changed tasks. For a run, enable the opt-in callback in integrations/ansible/callback_plugins, then read the saved events:
export ANSIBLE_CALLBACK_PLUGINS=/path/to/rcdo/integrations/ansible/callback_plugins
export ANSIBLE_CALLBACKS_ENABLED=rcdo
export RCDO_ANSIBLE_EVENTS=/path/to/new-run.jsonl
# Run your chosen ansible-playbook command separately.
rcdo ansible-watch --input /path/to/new-run.jsonl --require-host web-1 --require-host web-2The callback never records result bodies, variables or module arguments. workflow-check traces Terraform or OpenTofu outputs into Ansible host variables; see docs/terraform-ansible-workflow.md.
AWS and AliCloud
cloud-context-check compares an identity snapshot, or a live read with --collect, against the cloud, account and region you expect. A mismatch is critical. AWS collection with collect requires an explicit expected account and region. See docs/live-operations.md.
Google Cloud
Project and account checks, read-only Compute Engine collection scoped to one project and one zone, and create-command previews for networks, subnets, buckets and service accounts. rcdo never logs in, switches configuration or runs the generated commands. Authenticated cloud acceptance is still pending. See docs/google-cloud.md.
Comparing clouds
service-map and service-compare define comparable services and compare two to sixteen normalized deployments. Built-in mappings cover object and block storage on AWS, Azure, Google Cloud and Oracle Cloud. See docs/service-comparison.md.
GitHub Actions and Spacelift
gha-tool checks workflow permissions, action pinning, secret handling and unsafe triggers. spacelift-check reviews run identity, policy and approval evidence; basic live collection through spacectl api lacks policy evidence and returns INCOMPLETE. integrations/workflow/ contains Python recorders and exporters for workflow evidence.
Missing Utils evidence
Several commands read artifacts produced by Missing Utils: context reads a contextsnap snapshot, watch reads an eventwhy artifact, receipt-review reads runreceipt evidence and jsonprobe-check imports aggregate jsonprobe readiness results:
rcdo jsonprobe-check --input readiness-source.json --require api-health \
--environment staging --format jsonMissing required checks and evidence older than --max-age (15 minutes by default) are INCOMPLETE; failed checks block the review. docs/missing-utils-workflow.md has a local demonstration run from a sibling Missing Utils checkout.
Limits
- Checks are guardrails, not proof of safety. A later local success never makes an earlier failure or a deployment successful.
- Actual screen-reader, braille-display and magnification use has not yet been measured. Automated width and control-character checks do not establish it.
rcdo pilotrecords an operator's acceptance pass. - No live employer credentials were used during development. Authenticated AWS, Google Cloud, Spacelift and workplace workflow validation is listed as open work.
watchreviews a finite saved artifact. Continuous live monitoring is not implemented.permission-checkreads one policy document. An Allow is not an effective-access decision, and conditions are reported as incomplete.ansible-scopedoes not expand roles or templated limits, and the effective remote user is always unproven.prebuilddoes not expand roles.to-markdowndoes not perform OCR;seedoes not read text inside images.- Hashes and caller-supplied receipts show local consistency only. Signed or authenticated evidence is planned.
- Planned, not yet done (from
TODO.md): provider exporters for service comparison, mappings beyond storage, broader Google Cloud coverage, and ashell2seeplugin wrapper.
How it fits with the other tools
rcdo and Missing Utils share one roadmap. Missing Utils does bounded collection, normalization and process evidence with stable machine-readable schemas. rcdo does the nonvisual side: navigation, previews, interpretation, expectations, review state, runbook progress and handoffs. Each works on its own with files and pipes; neither needs AI or a daemon.
Links
- Full README on GitHub
- Shared roadmap
- Workflow guides in docs/
- Shift brief guide
- Delivery status and validation gaps
- Example inputs and policies
- GPL-3.0-or-later license
- Issue tracker
Built from the public rcdo repository (README, LICENSE, ROADMAP.md, TODO.md, Makefile, go.mod, .tool-versions, cmd/, toolkit/run.go, docs/shift.md, docs/beta-demo.md, docs/workflows.md, docs/google-cloud.md, docs/plugins.md, docs/rego.md, docs/operator-workflows.md, docs/missing-utils-workflow.md, docs/accessible-operations/STATUS.md, shell2see/README.md, examples/) at commit 4394c0f.