The docx-plus CLI¶
cli/ is the console entry point registered in pyproject.toml as
docx-plus = "docx_plus.cli:main" (and runnable as
python -m docx_plus.cli). It is a thin argparse shell over the
library: build_parser() registers one subparser per subcommand, and
main(argv) dispatches to the matching handler, returning 0 on
success, 1 for a handled DocxPlusError (printed to stderr), and 2
when no command is given.
The full command reference — every flag, with worked examples — is the CLI page.
Seven subcommands, six of them wrapping one tested library function each:
inspect— dump effective per-paragraph formatting (styles.resolve_effective_formatting).restyle— remap styles onto canonical ids (styles.remap_styles).controls— list / set / clear content-control values (controls).comments— list / resolve / reopen comment threads (comments).lint— report formatting defects (lint.lint). v0.6.plan— describe the repair without applying it (lint.plan_fixes). v0.6.skill— locate, read, or install the packaged agent skill (v0.5).
Read commands take --json; mutating commands require -o/--output
(or an explicit --in-place) so the input is never overwritten by
accident. Shared load/save plumbing and the CliError type live in
cli/_io.py, along with the --rule / --exclude / --no-tables /
--profile options lint and plan share.
lint and plan overload exit 1 as "I found something", which is what
lets either gate a CI step directly. Both are read-only, so there is
nothing to overwrite and the mutating-command convention does not apply
to them.
The CLI is the one layer that legitimately imports across
capabilities — it composes styles/ and controls/ by design — and is
the documented exception to the no-cross-imports
invariant.
skill — the packaged agent skill (v0.5)¶
The LLM-facing guide lived at repo-level skills/docx-plus/ through
v0.4, which meant docs/SKILLS.md claimed the library "ships" it while
linking only to GitHub blob URLs — broken for anyone who had
pip installed. v0.5 moved the tree to docx_plus/skill/.
That move needed no build configuration at all. Hatchling's
packages = ["docx_plus"] already sweeps non-.py files — the reason
py.typed ships — and the sdist include already lists docx_plus/.
Verified by building a wheel and unzipping it: all eleven Markdown files
present, then installed into a clean venv with no source tree and
driven through the CLI from there.
cli/skill.py is the one command that neither reads nor writes a
.docx, so the -o/--output / --in-place convention does not apply;
it takes --dest / --user plus a --force overwrite guard instead.
Two implementation notes:
- Resources are addressed as
files("docx_plus") / "skill", notfiles("docx_plus.skill"). The latter resolves through the namespace-package machinery and yields aMultiplexedPath, whosestr()isMultiplexedPath('…')— useless as the output ofskill path. Anchoring on the real package and navigating in gives a plainPath. _copy_treewalks theTraversableAPI rather than callingshutil.copytree, soskill installworks even from a zipimported distribution where there is no source directory to copy from.skill pathis the only action that cannot serve that case, and it raises aCliErrorsaying so.
The suite asserts that every reference topic is linked from SKILL.md
and that the frontmatter carries the name: / description: an agent
needs to discover the skill, so a new topic page cannot land orphaned.
See the agent skill page for how to use it.