After Dark Systems / Service Automation HubCompletely Programmable Infrastructure

OpenSAH / Utility guides

rcdo.

An accessible DevOps toolkit that reads noisy Terraform, OpenTofu, Ansible and cloud CLI output and reports what matters as plain, labelled findings for screen readers, braille and large print.

Early development (beta 1.3.0-beta.1) No tags or releases GPL-3.0-or-later

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.mod declares go 1.24.0; .tool-versions pins golang 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 toolUsed by
tofu or terraformtofu-check --plan (converts a saved plan with show -json) and iac-validate --native
AnsibleThe optional callback plugin that records events for ansible-watch; ansible-inventory --list output for ansible-scope. rcdo never launches Ansible itself.
AWS CLI, gcloud, azOpt-in live identity and inventory collection (cloud-context-check --collect, collect, context-acquire --native)
spacectlLive 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 pdftotextto-markdown for DOCX and PDF input
imgsee, pdfsee (from shell2see/)see, which reads image metadata and bounded PDF text
Python 3The 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 --version

That 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 --version

make 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 path

Quick 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 --sample

hcl2aws 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-only

tofu-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=never

prebuild 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-42

shift 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:

StatusExit codeMeaning
CLEAN0No findings, or a successful operation
REVIEW10Findings need review
BLOCKED20High or critical findings block the change
INCOMPLETE30Evidence is missing, stale or invalid
(error)2Invalid 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 FILE takes a JSON file of suppressions, each with an owner, a reason and an expiry date. See examples/policy.json.
  • Repository policy: .rcdo/policy.yaml assigns owners and severities to critical paths, requires companion changes such as runbooks, and rejects repository-specific content. See examples/repository-policy.yaml; it is checked by repo-policy-check and review.
  • Operational pack: ops-policy-check has built-in rules for public CIDRs, wildcard permissions, disabled encryption or deletion protection, and privileged workloads.
  • Rego: rego-check, rego-test, rego-diff and policy-review run your own Rego policies through a local OPA. Starter policies are in examples/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.

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/:

ProgramPurpose
cmd/rcdoThe main binary. It dispatches on its first argument, or on the name it was invoked as, so each symlink runs one command.
cmd/git-toolsCompatibility name for the same command suite.
cmd/git-diff-walkerCompatibility 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.

AreaCommands
Shift brief and readingshift, report-read, review-brief, review-session, handoff, markdown-view, to-markdown, see, log-read
Terraform and OpenTofuprebuild, tofu-check, plan-explain, plan-diff, iac-validate, iac-config-check, iac-context, state-walk, command-gen
Decomposition into manual runbooksdecompose, hcl2aws, hcl2ali, ansible2aws, ansible2ali
Ansible and Terraform-to-Ansible workflowsansible-check, ansible-scope, ansible-watch, workflow-check, workflow-trace, workflow-collect
Spaceliftspacelift-check, spacelift-runs, spacelift-diff, spacelift-watch
Cloud identity and inventorycontext, context-acquire, context-summary, cloud-context-check, collect, changes, resource-walk, fleet-check, kube-explain, network-check
Permissions and service comparisonpermission-check, permission-diff, service-map, service-compare, service-export
Git, pull requests and GitHub Actionsreview (also git-review), diff-walk, git-danger-check, git-isimportant-check, git-update-json, gha-tool, pr-manager, repo-policy-check
Policy and combined reviewops-policy-check, rego-check, rego-test, rego-diff, policy-review, deploy-review, review-change, evidence-pack
After a runreceipt-review, jsonprobe-check, error-explain, watch, monitor, audit
Structured configurationconfig-explain, config-diff, config-walk, config-set, config-remove
Operations and incidentsrunbook, runbook-check, incident, tasks
Setup and acceptanceconfig, 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-2

The 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 json

Missing 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 pilot records 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.
  • watch reviews a finite saved artifact. Continuous live monitoring is not implemented.
  • permission-check reads one policy document. An Allow is not an effective-access decision, and conditions are reported as incomplete.
  • ansible-scope does not expand roles or templated limits, and the effective remote user is always unproven. prebuild does not expand roles.
  • to-markdown does not perform OCR; see does 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 a shell2see plugin 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.

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.