acdc is the command-line entry point for the acdc AsciiDoc toolchain.
It converts documents, runs project lints and command blocks, displays a structural parser outline, and provides the AsciiDoc TCK adapter.
Use acdc <command> --help for the exhaustive option reference.
This guide focuses on common workflows and build-time features.
The default build includes HTML conversion, linting, pre-spec subs= compatibility, and the runtime convert --setext compatibility flag.
cargo build -p acdc-cli
cargo run -p acdc-cli -- convert document.adocOptional backends and tools are Cargo features:
cargo build -p acdc-cli --features pdf
cargo build -p acdc-cli --features terminal,highlighting
cargo build -p acdc-cli --all-featuresThe Release CLI workflow builds acdc with --all-features.
This includes all five output backends, highlighting, terminal emulation and HTML terminal previews, network support, linting, command execution, inspection, and the TCK adapter.
Rust and Zig are build prerequisites; users of the release binary do not need either toolchain.
The PDF fonts and Ghostty terminal library are embedded in the binary.
Command execution still needs the interpreter selected by each command block.
| Platform | Rust target | Build runner |
|---|---|---|
macOS ARM64 |
|
|
macOS x86-64 |
|
|
Linux x86-64 |
|
|
Linux ARM64 |
|
|
Windows x86-64 |
|
|
Linux builds target glibc 2.35 or later; older glibc systems and musl-based distributions are not covered by these archives. The workflow installs Zig 0.16.0 to build the bundled terminal library. Each platform runs the CLI tests in release mode, then extracts its archive and checks every output backend, including PDF and terminal rendering.
upload-rust-binary-action builds and packages the binaries and calculates SHA-256 checksums.
Archives are named acdc-X.Y.Z-TARGET.tar.gz on macOS and Linux, or acdc-X.Y.Z-TARGET.zip on Windows.
Each archive contains exactly four files at its root: acdc (or acdc.exe), LICENSE, OFL.txt, and LICENSE-NotoColorEmoji.txt.
The two font notices cover the embedded PDF fonts.
Each target also has an acdc-X.Y.Z-TARGET.sha256 file.
Extract the archive and put the executable in a directory on PATH; keep the license files with the distribution.
Manual runs upload build artifacts without creating a release.
A pushed acdc-cli-vX.Y.Z tag must match the CLI crate version and creates a draft GitHub release after all platform checks pass.
Review the archives and changelog before publishing the draft.
The CLI and LSP use separate workflows, tags, and versions.
Before tagging a new release, update the CLI crate version and lockfile, and move the relevant changelog entries into its release section. Use a new tag for each release; do not move an existing tag to newer code.
Convert one or more AsciiDoc files. HTML is the default backend in a default build; other backends must be selected explicitly.
acdc convert document.adoc
acdc convert --backend markdown --variant commonmark document.adoc
acdc convert --backend terminal --no-pager document.adocSupported backends depend on the features used to build the binary:
| Backend | Feature | Notes |
|---|---|---|
|
|
Standard HTML by default; |
|
|
Native roff/troff manual pages. |
|
|
GFM by default; |
|
|
PDF output backed by the Rust Typst engine. |
|
|
ANSI terminal output with an automatic pager on interactive stdout. |
--backend html5s remains an alias for --backend html --variant semantic.
Without --out-file, file input produces a backend-specific path next to each input.
Use --out-file - for stdout or --stdin for standard input.
acdc convert -o output.html document.adoc
acdc convert -o - document.adoc
printf '= Title\n\nBody.\n' | acdc convert --stdin -o -When --out-file is combined with several inputs, only the first input is processed.
--open opens converter-reported output files with the system’s default application and is ignored for stdout.
convert, lint, and inspect default to Unsafe mode for trusted local documents.
Use -S secure or --safe-mode secure to prevent include reads.
execute defaults to Safe. This mode restricts include paths but does not sandbox commands.
The parser library defaults to Secure.
Includes share a 64 MiB budget per input document, separate from safe mode.
Use --max-total-include-bytes BYTES to change it on convert, lint, inspect, or execute.
For example, this permits 256 MiB of selected include text for a trusted build:
acdc convert --max-total-include-bytes 268435456 book.adocThe budget counts selected text after indentation, including nested and repeated includes.
It excludes the entry document. Comments and inactive conditionals count before they are removed.
Zero permits only empty include selections; it does not mean unlimited.
Document attributes and -a cannot change the budget.
The 10 MiB per-include limit still applies, and small line selections from larger files still work.
See Include source size limit for the counting rules.
These resource limits deliberately differ from Asciidoctor.
Use --timings for parse/conversion timings, --strict to turn supported fallbacks into errors, --safe or --safe-mode for parser safety policy, and --embedded to suppress enclosing document structure where the backend supports embedded output.
Values passed with -a or --attribute take precedence over matching attribute entries in the document.
Use -a name, -a name=value, or -a name! to set, assign, or unset a locked value.
Add @ to the name or value, such as -a name@=value, -a name=value@, or
-a !name=@, when the document must be allowed to replace that command-line default.
Use --force-local-file-xrefs for combined or partially included documents whose
references still name the original files:
acdc convert --backend pdf --force-local-file-xrefs book.adocThe flag resolves chapter.adoc as [installation].
It also applies to text and keeps custom text.
A nonempty fragment is required. Multi-letter URI schemes and // prefixes
retain normal behavior. A single letter before : is treated as a Windows drive.
Page-only references are unchanged.
Use this override only when the fragment identifies the intended local anchor.
It also redirects genuine external file references and does not scope duplicate
IDs. Missing anchors produce warnings; --fail-on-warnings can make these fatal.
Cross-references never load their target files.
This flag does not resolve Antora resource IDs. Antora Assembler scopes anchors and resolves references before conversion; its prepared source does not need this override. Complete includes already resolve locally without the flag. The flag is disabled by default for every backend, including PDF.
Build with pdf (or all-backends) and select --backend pdf:
cargo run -p acdc-cli --features pdf -- convert --backend pdf document.adoc \
--page a3 \
--page-layout landscape \
--font-dir fonts \
--logo assets/logo.svg \
--title "Internal Architecture" \
--watermark "Draft" \
--watermark-timestamp \
--toc--page accepts A3, A4, A5, Executive, Legal, Letter, or Tabloid.
--page-layout accepts portrait or landscape.
The pdf-page-size document attribute also accepts custom dimensions, and
pdf-page-margin sets one to four margins for that document.
--theme selects a YAML theme, --plain removes page chrome, and --emit-typst writes the generated Typst markup for one input.
--strict makes unresolved PDF images or logos fatal.
Remote PDF assets additionally require the network feature and remain subject to the PDF converter’s asset safety policy.
Remote document images use up to two simultaneous requests by default.
Use --image-concurrency 1 for sequential fetching, or --image-concurrency 4
to permit four requests. Source and byte quotas can reduce the batch size.
Local images remain sequential, and warning order stays the same.
Interactive terminal output uses $PAGER, defaulting to less -FRX on Unix and more on Windows.
Use --no-pager or an empty PAGER to disable it.
The html-terminal feature enables acdc-specific terminal previews in HTML, including [terminal] blocks and source blocks opted in with :acdc-terminal:.
See the HTML converter documentation for the rendering syntax, attributes, replay support, and Asciidoctor differences.
The terminal-emulator feature enables Ghostty-backed [terminal] session rendering in the terminal backend and requires the documented Zig build prerequisite.
Pass an existing Asciidoctor PDF theme with an explicit format:
acdc convert --backend pdf --theme brand-theme.yml --theme-format asciidoctor document.adocacdc converts supported Asciidoctor PDF 2.3.15 settings during theme loading.
It reports unsupported settings and differences as converter warnings.
Use --fail-on-warnings to get exit status 1 while retaining the generated PDF.
The default theme format is still acdc; native theme validation stays strict.
Supported settings include RGB colours, font families and sizes, captions, tables,
book page breaks, and page geometry. The loader handles earlier-value references,
numeric expressions, and the pinned base and default parent themes.
External parent themes and theme font catalogs are not loaded. Supply custom
fonts with --font-dir. The two PDF engines can produce different layouts.
See the compatibility map
for supported settings and fallback behavior. This command requires the pdf build feature.
To inherit supported Asciidoctor defaults, start a custom theme with
extends: default and add only your overrides. Unsupported styles use acdc defaults.
Save the full resolved theme in native acdc format, then use it without the compatibility option:
acdc convert --backend pdf --theme brand-theme.yml --theme-format asciidoctor --emit-theme-config acdc.yml document.adoc
acdc convert --backend pdf --theme acdc.yml document.adocThe first command generates both the PDF and the native theme file.
A document or --stdin is required. Omit --theme to use the selected format’s
bundled defaults. The theme file includes all native tokens and theme page
defaults. It excludes document attributes, caller page overrides, and font files.
Conversion warnings still apply;
--fail-on-warnings retains the exported file and returns status 1.
The default build includes the lint command:
acdc lint docs/*.adoc
acdc lint --output-style compact --deny image-alt-text docs/*.adocLint levels follow the Clippy/rustc shape: --allow/-A, --warn/-W, --deny/-D, and --forbid/-F.
Individual lint IDs can be scoped to source locations:
acdc lint -A section-title-capitalization@37 docs/architecture.adoc
acdc lint -D image-alt-text@10:1-10:80 docs/architecture.adocScopes support LINE, START-END, LINE:COLUMN, and LINE:COLUMN-LINE:COLUMN; comma-separated locations can follow one @.
Full diagnostics and lint statistics are the default.
Compact output omits colors and source snippets.
See the lint crate documentation for lint IDs, groups, levels, and location semantics.
Build with inspect to print a human-readable structural outline of a parsed file.
It honors file context and local includes; it is not a lossless AST serialization.
cargo run -p acdc-cli --features inspect -- inspect document.adoc --show-locations--max-depth limits displayed nesting.
Color is used only on interactive stdout and respects NO_COLOR.
Build with execute to run command blocks defined in an AsciiDoc document.
A command block is a listing or source block carrying the command role and an explicit id.
Ids contain only ASCII letters, digits, _, and -; they must be nonempty and cannot start with -.
The optional deps attribute names prerequisites, separated by commas.
The optional description attribute supplies a summary for --list.
== Build
[.command, id=build, description="Build the project"]
[source, bash]
----
cargo build
----
== Test
[.command, id=test, deps="build", description="Run the tests"]
[source, bash]
----
cargo nextest run
----acdc execute --dry-run README.adoc
acdc execute --list README.adoc
acdc execute --id build README.adoc
acdc execute --id-regex '^test-' --exit-on-failure README.adoc
acdc execute --id test --cwd project --env MODE=ci README.adocCommands are discovered in document order, including inside nested containers, AsciiDoc table cells, and included files, then executed in dependency order.
Exact --id and --id-regex selectors form a union, and selected commands always run together with their transitive dependencies; each command runs at most once.
Without selectors, every command is selected.
An unknown id or a regex that matches no commands is an error.
--dry-run prints the selected commands and scripts; --list prints a bulleted list with labeled ids, interpreters, enclosing section titles, direct dependencies, and optional descriptions.
Both include dependencies and run no commands; the two options cannot be combined.
For the example above, --list prints:
- id=build, interpreter="bash", section="Build", description="Build the project"
- id=test, interpreter="bash", section="Test", deps="build", description="Run the tests"Dependency ids are sorted alphabetically. The section is the nearest enclosing section’s title as plain text; commands outside sections omit it. Interpreters, section titles, and descriptions are quoted, with control characters escaped to keep each command on one line.
The block attribute interpreter overrides the source language: [source,python,role=command,id=check,interpreter=python3] uses Python highlighting and runs python3.
Without an override, the source language selects the interpreter; a block without either uses sh.
The interpreter is one executable name or path, passed directly to the operating system without shell argument splitting or an allowlist.
Relative interpreter paths are resolved from the caller’s working directory, including when --cwd is set; bare executable names use the operating system’s search rules.
Includes and conditionals are processed before execution.
Preprocessing normalizes line endings and removes trailing whitespace from lines.
Script bodies are literal by default, including attribute references and callout markers.
Enable attribute expansion with subs=attributes, subs=attributes`, or `subs=attributes on a command block.
The normal group also enables attributes; subs=none and subs=-attributes keep them literal.
Only enabled attribute references are expanded; other rendering substitutions do not change the script, and callouts remain literal.
Use comments in the script language for annotations.
:target: build-output
[.command,id=show-target,subs=+attributes]
----
printf '%s\n' '{target}'
----Attribute values are inserted as text without shell quoting; write the quoting required by the selected interpreter.
When attribute expansion is enabled, {name} becomes literal {name} without looking up the attribute.
An empty attribute value is valid; a missing unescaped attribute is an error.
Each command uses the attributes active at its source position.
Attributes defined inside an AsciiDoc table cell stay in that cell; values inherited by the cell cannot be reassigned there.
All scripts are prepared before selection or execution, so a missing attribute in an unselected command also stops the invocation.
Dry-run displays the same prepared script that execution passes to the interpreter.
Malformed command blocks, incomplete structural recovery, and missing required includes are errors before any command starts.
A command that exits with a nonzero status blocks its dependent commands; independent commands still run.
--exit-on-failure stops at the first failed command.
A signal termination or an error creating the script or starting its interpreter always stops the run.
Any failed command makes the invocation fail, including when independent commands finish successfully.
Each command inherits the caller’s working directory, environment, and standard streams.
--cwd PATH changes the child working directory; relative paths are resolved from the caller’s directory.
It does not change how the input document or its includes are resolved.
Repeat --env NAME=VALUE to override variables for the children; the last value for a name wins.
An empty value is allowed, and only the first = separates the name from its value.
These options leave the calling process unchanged.
-S/--safe-mode limits what the document may include while parsing; it does not sandbox the executed commands.
A build with the execute feature only is available via cargo build -p acdc-cli --no-default-features --features execute.
Add pre-spec-subs to that feature list to enable command attribute substitutions.
Without this feature, documents that request any subs setting are rejected before execution.
| Feature | Default | Effect |
|---|---|---|
|
yes |
HTML backend. |
|
yes |
Lint command. |
|
yes |
Asciidoctor-compatible pre-spec |
|
yes |
Compiles Setext header support; parsing is enabled per run with |
|
no |
Optional output backends. |
|
no |
Source highlighting in each selected HTML or terminal backend; does not select a backend. |
|
no |
HTML terminal previews and session/replay rendering. |
|
no |
Ghostty-backed terminal session rendering; selects the terminal backend. |
|
no |
Remote includes and remote PDF assets when PDF is selected. |
|
no |
|
|
no |
Developer/specification commands. |
Convenience groups are all-backends, dev-tools (execute, inspect), and test-tools (tck).
A build with no command-enabling features exits with a diagnostic that lists the available command features.
Parser and converter warnings are written to stderr with source snippets when available.
Use acdc convert --fail-on-warnings to exit with status 1 when parsing,
preprocessing, or conversion emits a structured warning. Each warning is shown
once. Warnings do not stop processing of other selected inputs. Terminal pager
warnings appear after the pager exits. Logging and CLI notices do not affect
this option.
Successful output is retained, including files, stdout, and pager output.
--open does not open generated files when warnings make the command fail.
Without this flag, warnings keep their existing behavior and permit status 0.
--strict still makes its selected non-conformance and asset fallbacks fatal;
the two flags can be used together. The warning exit and output retention are
similar to Asciidoctor’s --failure-level WARN.
acdc convert --fail-on-warnings guide.adoc
acdc convert --strict --fail-on-warnings -o - guide.adocLint diagnostics use the selected output style. Command-line usage errors exit with status 2; processing failures and denied lint diagnostics exit with status 1; successful commands exit with status 0.