---
title: "CLI overview"
description: "How the monedula-acl-rbac CLI is organized: the run directory, logging flags and environment variables, output formats and exit codes."
url: https://monedula.dev/flock/docs/acl-rbac-converter/reference/cli/
---
Every command has the form `monedula-acl-rbac <command> [flags]`; each command page lists its flags and exit codes. The reference describes version 0.10.0.

## Commands

| Command | Purpose | Changes external state |
| --- | --- | --- |
| [`extract`](/flock/docs/acl-rbac-converter/reference/cli/extract/) | Read ACLs from one of nine sources into a canonical `acls.json`. | No |
| [`plan`](/flock/docs/acl-rbac-converter/reference/cli/plan/) | Turn `acls.json` into `plan.json` and `report.txt`. `--revalidate` re-checksums an edited plan. | No |
| [`report`](/flock/docs/acl-rbac-converter/reference/cli/report/) | Print the report of a `plan.json` again, as text, Markdown or JSON. | No |
| [`apply`](/flock/docs/acl-rbac-converter/reference/cli/apply/) | Create the plan's role bindings in MDS. `--dry-run` previews the calls. | Yes |
| [`verify`](/flock/docs/acl-rbac-converter/reference/cli/verify/) | Check in MDS that each source ACL's access is granted. | No |
| [`delete-acls`](/flock/docs/acl-rbac-converter/reference/cli/delete-acls/) | Write the script that deletes the converted Allow ACLs, and its rollback script. | Writes a script you run |
| [`delete-deny-acls`](/flock/docs/acl-rbac-converter/reference/cli/delete-deny-acls/) | Write the script that removes DENY ACLs after a live re-check, and its rollback script. | Writes a script you run |
| [`emit`](/flock/docs/acl-rbac-converter/reference/cli/emit/) | Render a plan as a Confluent CLI script, CFK manifests or MDS `curl` commands. | No |
| [`convert`](/flock/docs/acl-rbac-converter/reference/cli/convert/) | Extract, plan and emit from a file in one call, without a run directory. | No |
| [`discover`](/flock/docs/acl-rbac-converter/reference/cli/discover/) | Query MDS for cluster IDs and print a `scopes.yaml` stub. | No |
| [`init`](/flock/docs/acl-rbac-converter/reference/cli/init/) | Write a starter `scopes.yaml` and `rules.yaml` into a directory. | No |
| [`status`](/flock/docs/acl-rbac-converter/reference/cli/status/) | Summarize the state of a run directory. | No |
| [`diff`](/flock/docs/acl-rbac-converter/reference/cli/diff/) | Compare two `acls.json` or two `plan.json` files. | No |
| [`mds list-bindings`](/flock/docs/acl-rbac-converter/reference/cli/mds-list-bindings/) | List the role bindings MDS holds for given principals. | No |
| [`auth login`](/flock/docs/acl-rbac-converter/reference/cli/auth-login/) | Log in to MDS interactively and cache the token. | No; writes a local token cache |
| [`rules show`](/flock/docs/acl-rbac-converter/reference/cli/rules-show/) | Print the built-in mapping rules. | No |
| [`completion bash`](/flock/docs/acl-rbac-converter/reference/cli/completion-bash/), [`zsh`](/flock/docs/acl-rbac-converter/reference/cli/completion-zsh/), [`fish`](/flock/docs/acl-rbac-converter/reference/cli/completion-fish/), [`powershell`](/flock/docs/acl-rbac-converter/reference/cli/completion-powershell/) | Generate the completion script for that shell. | No |

`monedula-acl-rbac --version` prints the version, the commit and the build date.

## The run directory

The migration commands read and write their artifacts in a run directory. A command picks it in this order:

1. `--run-dir`.
2. The parent directory of `--out`.
3. The directory of the input artifact, such as `--plan` for `apply` or `--acls` for `plan`.
4. The environment variable `MONEDULA_ACL_RBAC_RUN_DIR`.
5. A new `runs/<UTC timestamp>/` in the current directory, such as `runs/2026-05-21T10-00-00Z/`, with a `-2`, `-3` and so on suffix if that name exists.

The directory is created with mode 0700. Its files:

| File | Written by | Contents |
| --- | --- | --- |
| `acls.json` | `extract` | The canonical ACL snapshot. |
| `extract.log`, `extract-source.json` | `extract` | How and from where the ACLs were read. |
| `existing-bindings.json` | `extract --from cfk` or `k8s` | Role bindings that already exist, which `plan` marks `SKIP_EXISTS`. |
| `plan.json`, `plan.json.sha256` | `plan` | The plan and its checksum. |
| `report.txt` | `plan` | The readable report of the plan. |
| `would-apply.log` | `apply --dry-run` | Every call `apply` would make, with request bodies. |
| `apply.log` | `apply` | Every MDS call and its result. |
| `.lock` | `apply` | The lock held while `apply` runs. |
| `verify.json` | `verify` | The result of every check, stamped with the plan's SHA-256. |
| `delete-acls.sh`, `deleted-acls.json`, `rollback.sh` | `delete-acls` | The deletion script, the ACLs it removes and the script that recreates them. |
| `delete.log` | `delete-acls.sh` | One `OK` or `FAIL` line per ACL. |
| `delete-deny-acls.sh`, `deleted-deny-acls.json`, `rollback-deny.sh` | `delete-deny-acls` | The DENY deletion script, its ACLs and its rollback script. |
| `runtime.env` | `delete-deny-acls` | Connection settings, credential references and a per-run token for the DENY script; mode 0600, deleted when the script exits. |
| `delete-deny.log` | `delete-deny-acls.sh` | One `OK`, `SKIP` or `FAIL` line per DENY ACL. |

## Global flags

Two flags work on every command:

- `--log-format`: `text` (default) or `json`, for piping structured logs into a CI or observability stack.
- `--log-level`: `debug`, `info` (default), `warn` or `error`.

Diagnostic logs go to stderr. The audit files in the run directory, such as `apply.log` and `verify.json`, keep their own line formats whatever `--log-format` says.

## MDS connection flags

`apply`, `verify`, `discover` and `mds list-bindings` connect to MDS with these flags, and `delete-deny-acls` passes them on to the script it generates. `auth login` takes the URL and TLS flags only.

- `--mds-url`: the MDS base URL. Required.
- `--mds-token-file`: a file with a pre-fetched bearer token.
- `--mds-user` and `--mds-password-file`: a user name and a file with its password, exchanged for a token.
- `--cache-token`: store the resolved token in the user configuration directory, under `monedula-acl-rbac/tokens/`, for later commands.
- `--mds-ca-cert`, `--mds-client-cert`, `--mds-client-key`: a PEM CA bundle, and a client certificate and key for mutual TLS.
- `--mds-insecure-skip-verify`: skip certificate verification, with a warning on every run. For development clusters only.
- `--mds-max-retries`: retries of transient failures after the first call, 3 by default; 0 turns them off.

Credentials resolve in this order: the token file, then the user name and password, then a token cached by `auth login` or `--cache-token` for the same URL and operating-system user. `delete-deny-acls` does not accept a cached token alone, because its script authenticates later, without you.

## Kafka connection flags

`extract --from live` connects to Kafka with these flags, and `delete-acls` and `delete-deny-acls` write them into the scripts they generate:

- `--bootstrap-server`, or its alias `--bootstrap`: the bootstrap servers, comma-separated.
- `--command-config`: a Kafka client properties file, as for `kafka-acls.sh`, with the TLS and SASL settings.

## Environment variables

| Variable | Effect |
| --- | --- |
| `MONEDULA_ACL_RBAC_LOG_FORMAT`, `MONEDULA_ACL_RBAC_LOG_LEVEL` | Defaults for `--log-format` and `--log-level`. |
| `MONEDULA_ACL_RBAC_MDS_URL` | Default for `--mds-url`. |
| `MONEDULA_ACL_RBAC_MDS_TOKEN_FILE` | Default for `--mds-token-file`. |
| `MONEDULA_ACL_RBAC_MDS_USER`, `MONEDULA_ACL_RBAC_MDS_PASSWORD_FILE` | Defaults for `--mds-user` and `--mds-password-file`. |
| `MONEDULA_ACL_RBAC_MDS_CA_CERT`, `MONEDULA_ACL_RBAC_MDS_CLIENT_CERT`, `MONEDULA_ACL_RBAC_MDS_CLIENT_KEY` | Defaults for the MDS TLS flags. |
| `MONEDULA_ACL_RBAC_MDS_INSECURE_SKIP_VERIFY` | `1`, `true` or `yes` turns on `--mds-insecure-skip-verify`. |
| `MONEDULA_ACL_RBAC_MDS_MAX_RETRIES` | Default for `--mds-max-retries`. |
| `MONEDULA_ACL_RBAC_RUN_DIR` | The run directory when no flag or input artifact names one. |
| `MONEDULA_SKIP_PLAN_HASH_CHECK` | `1` makes the generated deletion scripts skip their `plan.json` hash check, for a script run away from its run directory. |
| `MONEDULA_KAFKA_ACLS_BIN` | The Kafka ACL tool that the DENY deletion script calls, `kafka-acls` by default. |

## Output formats

Commands that print a structured summary take `--format`:

| Command | `--format` values | Default |
| --- | --- | --- |
| `apply` | `text`, `json` | `text` |
| `verify` | `text`, `json` | `text` |
| `diff` | `text`, `json` | `text` |
| `mds list-bindings` | `text`, `json`, `yaml` | `text` |
| `report` | `text`, `json`, `markdown` | `text` |
| `status` | `text`, `json` | `text` |
| `emit` | `script`, `cfk`, `mds-curl` | `script` |
| `convert` | `script`, `cfk`, `mds-curl` | `script` |

For `emit` and `convert`, `--format` picks the shape of the artifact rather than the encoding of a summary. `plan`, `extract`, `delete-acls`, `delete-deny-acls`, `discover`, `init`, `auth login` and `rules show` produce a single artifact and have no `--format`. No command writes CSV.

The JSON documents carry `schema_version: "1"` and are described by JSON Schemas:

| Document | Schema reference |
| --- | --- |
| `acls.json` | [acls.v1.json](/flock/docs/acl-rbac-converter/reference/formats/acls-v1/) |
| `plan.json` | [plan.v1.json](/flock/docs/acl-rbac-converter/reference/formats/plan-v1/) |
| `apply --format json` | [apply-summary.v1.json](/flock/docs/acl-rbac-converter/reference/formats/apply-summary-v1/) |
| `verify --format json` and `verify.json` | [verify-summary.v1.json](/flock/docs/acl-rbac-converter/reference/formats/verify-summary-v1/) |
| `status --format json` | [status.v1.json](/flock/docs/acl-rbac-converter/reference/formats/status-v1/) |
| `report --format json` | [report.v1.json](/flock/docs/acl-rbac-converter/reference/formats/report-v1/) |

The JSON output of `diff` and `mds list-bindings` carries `schema_version: "1"` as well, without a published schema.

## Exit codes

| Code | Meaning |
| --- | --- |
| 0 | Success. For `verify`, every result is OK. |
| 1 | Usage error: a missing required flag, a malformed argument, an unknown command or flag, a missing acknowledgement flag such as `--i-understand-this-is-destructive`, or a confirmation that was refused or impossible without `--confirm` outside a terminal. |
| 2 | Input error: a malformed or unreadable input file, such as the `acls.json`, `scopes.yaml`, `rules.yaml` or `principals.yaml` that `plan` reads, the `vars.yaml` of `extract --from script`, the `plan.json` that `report` or `emit` reads, or a `verify.json` that is malformed or was made for a different plan. |
| 3 | The plan has unmapped or rejected ACLs: `plan` without `--allow-unmapped` or `--allow-rejected`, and `report --strict`. |
| 4 | External system error: MDS unreachable or refusing the credentials, Kafka unreachable or failing authentication, or the Kubernetes API unreachable or denying access. Errors the CLI does not classify also exit 4. |
| 5 | A guardrail refused or reports an unhealthy state: a `plan.json` that no longer matches its checksum, `verify` with any missing or unknown result, or `init` refusing to overwrite a file. |

Because unclassified errors fall back to 4, some refusals exit 4 rather than 5:

- `apply` when the run directory's lock is held, or stale and not cleared with `--force-unlock`.
- `delete-acls` when no ACL is eligible for deletion, or when `acls.json` changed since planning.
- `delete-deny-acls` when any `verify` result is not confirmed, or when no DENY ACL is eligible, which includes every wildcard-principal DENY.

For the same reason, some commands report an unreadable or invalid input file with 4 rather than 2, for example `convert` and `diff`.

The generated deletion scripts exit 5 when `plan.json` changed since generation or cannot be hashed, and the DENY script also when `runtime.env` is missing or not mode 0600. Each command page lists the exact codes of that command.