{"id":51010805,"url":"https://github.com/lipex360x/docx_builder","last_synced_at":"2026-06-21T02:02:43.681Z","repository":{"id":361032756,"uuid":"1244974868","full_name":"lipex360x/docx_builder","owner":"lipex360x","description":"Generate DOCX reports from a content.yaml file","archived":false,"fork":false,"pushed_at":"2026-05-28T22:30:18.000Z","size":223,"stargazers_count":0,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-29T00:16:01.880Z","etag":null,"topics":["cli","document-generation","docx","python","yaml"],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lipex360x.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-20T19:34:38.000Z","updated_at":"2026-05-28T22:30:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lipex360x/docx_builder","commit_stats":null,"previous_names":["lipex360x/docx_builder"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/lipex360x/docx_builder","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipex360x%2Fdocx_builder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipex360x%2Fdocx_builder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipex360x%2Fdocx_builder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipex360x%2Fdocx_builder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lipex360x","download_url":"https://codeload.github.com/lipex360x/docx_builder/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lipex360x%2Fdocx_builder/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34591166,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-21T02:00:05.568Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","document-generation","docx","python","yaml"],"created_at":"2026-06-21T02:02:43.019Z","updated_at":"2026-06-21T02:02:43.674Z","avatar_url":"https://github.com/lipex360x.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# docx_builder\n\n![Python](https://img.shields.io/badge/python-3.11%2B-blue)\n![Version](https://img.shields.io/badge/version-0.10.0-blue)\n\n\u003e Assemble structured Word documents from a YAML content file (and an optional `.docx` cover template), runnable from any working directory.\n\nDefine headings, body text, bullet points, figures, references, and a table of contents in `content.yaml`. Install the tool once, then run `docx_builder build` from any project directory. The package is content-agnostic: it ships no cover templates and no sample content. You bring your own.\n\n## Contents\n\n- [How it works](#how-it-works)\n- [Install](#install)\n- [Quick start](#quick-start)\n- [content.yaml reference](#contentyaml-reference)\n- [Styles](#styles)\n- [Project structure](#project-structure)\n- [CLI reference](#cli-reference)\n- [Development](#development)\n\n---\n\n## How it works\n\n1. Create a directory for your document with a `content.yaml` file (and an `images/` folder if you use figures).\n2. Run `docx_builder build` from that directory. It reads the YAML, optionally loads a `.docx` cover template (only when `cover.template` is set; nothing is bundled), fills the cover table by row index, and renders every section in order.\n3. On macOS with Microsoft Word, `build` finalises the table of contents for you when the document declares one. On Windows or Linux the `.docx` is still generated normally, but the TOC stays as a placeholder — open it in Word and refresh fields (`Ctrl+A`, then `F9`) to populate it. Automatic TOC finalisation and PDF export are macOS-only.\n\n```\ncontent.yaml + images/ ──► docx_builder build ──► \u003coutput\u003e.docx\n```\n\nPage numbers are added automatically to the `sections:` block. Items in `front_matter:` (cover sheet, TOC) are excluded from the footer counter but still count toward the total.\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n\n---\n\n## Install\n\nInstall once as a global tool with `uv`, straight from the repository:\n\n```bash\nuv tool install git+https://github.com/lipex360x/docx_builder.git\n```\n\nOr from a local clone:\n\n```bash\nuv tool install .                  # snapshot install\nuv tool install --editable .       # live install, source edits propagate without reinstall\n```\n\nThis registers the `docx_builder` binary in `~/.local/bin/`. Because the package is content-agnostic, provide your own cover `.docx` through `cover.template` or `--template-dir` when you want a cover sheet.\n\nThe core install has no PDF post-processing dependency. The opt-in `--fix-toc-links` flag needs the `pdf-links` extra, which adds [PyMuPDF](https://pymupdf.readthedocs.io/):\n\n```bash\nuv tool install 'git+https://github.com/lipex360x/docx_builder.git[pdf-links]'\n```\n\nTo upgrade a **snapshot** install after pulling changes:\n\n```bash\nuv tool install --reinstall .\n```\n\n\u003e [!TIP]\n\u003e An **editable** install (`uv tool install --editable .`) picks up `.py` and bundled-data edits automatically. Reinstall only when `[project.scripts]` entries or dependencies change.\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n\n---\n\n## Quick start\n\n### 1. Create a project anywhere\n\n```bash\nmkdir -p ~/projects/my-report\ncd ~/projects/my-report\ndocx_builder init\n```\n\n`init` scaffolds a **role-based project structure**: a `report/` directory (with `content.yaml`, `images/`, `assets/`, `output/`, `templates/`), a single conditional `CLAUDE.md`, a `.gitignore` and a `.work/` scratch dir. Add optional layers with `--with brief,references,src,meta,tools,monitor,ai-check` (dependencies auto-resolved), or `--full` for all of them plus the embedded, race-safe `screenshot_intake.py` (the `monitor` layer). `--name` is injected into `CLAUDE.md` and `content.yaml` (it defaults to the directory name); `--cover` writes a cover + TOC `content.yaml` (Shape B). The scaffolder is **idempotent**: re-running only adds what is missing and never overwrites existing files without `--force`. The generated `content.yaml` is a starter with `Replace me.` body text, so you still author the real content for whatever you are building: CV, report, manual, paper, contract, or fiction. `build` resolves `content.yaml` from the project root, falling back to `report/`, so `docx_builder build .` works on a scaffolded project.\n\n### 2. Edit `content.yaml`\n\n```yaml\ncover:                                 # optional, omit for a sectionless document\n  template: ../templates/MyCover.docx  # your own .docx, nothing is bundled\n  output: \"Report_{number}.docx\"       # placeholders: any string field under cover\n  number: \"0001\"\n  rows:                                # one per row of the cover table, in order\n    - Project Name\n    - Document Title\n    - Author Name\n    - \"0001\"\n    - \"2026-06-15\"\n\nstyles:                                # optional, overrides built-in defaults\n  h1:   { font_size: 16pt, color: \"#003366\" }\n  body: { align: justify }\n\nfront_matter:                          # rendered first, no page numbers\n  - call: page_break\n  - call: toc\n    levels: 1-2\n\nsections:                              # rendered after, page numbers start here\n  - call: h1\n    text: Introduction\n\n  - call: body\n    text: This is the opening paragraph.\n\n  - call: figure\n    filename: diagram.png\n    label: Figure 1.1\n    caption: System overview\n    width: 5in\n```\n\n### 3. Build\n\n```bash\ndocx_builder build\n# Saved: /Users/you/projects/my-report/Report_0001.docx\n# Report:\n#   Words: 1240\n#   Reading time: ~6 min\n#   Pages: n/a (known only after export to PDF)\n#   Em-dashes (U+2014): 0\n```\n\nAfter saving, `build` prints a short report: word count, estimated reading time (at 200 wpm), a page-count line, and an em-dash (`U+2014`) counter. When em-dashes are present the line is flagged `\u003c- remove before shipping`. The page count is `n/a` for a plain build because only the Word/PDF export path can determine the real count.\n\nOr specify a directory:\n\n```bash\ndocx_builder build /path/to/some-other-project\n```\n\n### 4. The table of contents\n\nWhen your document declares a `toc` section, `build` finalises it automatically on macOS with Microsoft Word: it drives Word to update every table of contents and all fields, then writes the populated `.docx` back over the source. No manual `F9`, no PDF required.\n\n```bash\ndocx_builder build --no-finalize    # skip the Word pass, keep build pure and fast\n```\n\n\u003e [!NOTE]\n\u003e Off macOS or without Word installed, `build` cannot fill the TOC (it is a Word field that only Word can repaginate). It leaves a placeholder, prints a short note, and exits cleanly. On Windows, open the `.docx` in Word and press `Ctrl+A` then `F9` to populate it (`Cmd+A` on macOS). PDF export is macOS-only.\n\nFor PDF, the export drives Word for you on macOS:\n\n```bash\ndocx_builder export pdf\n# Exported: /Users/you/projects/my-report/Report_0001.pdf (2 pages)\n\ndocx_builder build --pdf            # build then export in one command\ndocx_builder build --pdf --open     # and open both the PDF and the finalised .docx in Word\n```\n\n\u003e [!WARNING]\n\u003e The reported page count is read from the actual PDF. The cached `\u003cPages\u003e` value inside the `.docx` is unreliable and is never trusted.\n\nBy default the export also writes the populated TOC back over the source `.docx`, so the source ends finalised. Pass `--no-update-source` to leave it byte-identical, useful when `export pdf --input SomeFile.docx` points at a file you do not want overwritten. `--open` is macOS-only; elsewhere it prints a note and skips.\n\n\u003e [!NOTE]\n\u003e **Known Word limitation: ToC hyperlinks in the PDF.** In the exported PDF, the clickable table-of-contents entries can occasionally jump to the heading one entry ahead of the target (clicking an entry lands on the next heading). This is a bug in Word for Mac's Save-as-PDF engine: the generated `.docx` bookmarks are correct, and page numbers and content are unaffected. The bug is rare, so the fix is opt-in: pass `--fix-toc-links` to `export pdf` or `build --pdf` to post-process the PDF and rewrite each ToC link to its heading's real page (it prints `Fixed N ToC link(s)`). This requires the optional `pdf-links` extra (`uv tool install 'docx_builder[pdf-links]'`); the default export path is unchanged and gains no new dependency.\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n\n---\n\n## content.yaml reference\n\nEvery top-level block is optional. The minimal valid `content.yaml` produces a blank document. Realistic shapes:\n\n### Top-level blocks\n\n| Block | Type | Description |\n|-------|------|-------------|\n| `cover` | mapping | Optional cover sheet. When omitted, no template is loaded and a blank document is used. |\n| `styles` | mapping | Optional visual overrides, see [Styles](#styles). |\n| `page_numbers` | bool | Default `true`. Set `false` to disable the footer counter everywhere. |\n| `front_matter` | list | Sections rendered first, **without** page numbers (cover sheet items, TOC). |\n| `sections` | list | Sections rendered after `front_matter`, **with** page numbers (unless `page_numbers: false`). |\n\n### Cover fields\n\n| Field | Required | Description |\n|-------|----------|-------------|\n| `template` | no | `.docx` cover template. Absolute path, relative path with separators (anchored at project dir), or bare filename (looked up in `--template-dir`). Omit for a blank document. |\n| `output` | no | Output filename pattern. Placeholders are any string field defined under `cover` (e.g. `{number}`, `{name}`). Defaults to `Report_{number}.docx`. |\n| `number` | no | Document identifier, exposed as `{number}` to `output`. |\n| `rows` | no | Strings filled into the cover table by row index. Row 0 maps to row 0 of the `.docx` table, into the second column. |\n| `ai_declaration` | no | Optional paragraph appended after the cover table with a bold \"AI Use Declaration:\" prefix. |\n\n### Section types\n\n| `call` | Required fields | Optional fields | Description |\n|--------|-----------------|-----------------|-------------|\n| `page_break` | (none) | (none) | Hard page break |\n| `toc` | (none) | `levels` (default `\"1-2\"`) | Word TOC field, populated by `build` on macOS+Word or via `Cmd+A` then `F9` |\n| `h1` / `h2` / `h3` | `text` | `style` | Headings 1 to 3 (default colour is black) |\n| `body` | `text` | `style` | Body paragraph |\n| `bullet` | `text` | `style` | Bulleted item with configurable glyph |\n| `bold_lead` | `bold`, `rest` | `style` | Bullet with bold lead phrase followed by regular text |\n| `reference` | `text` | `style` | Hanging-indent paragraph for bibliography entries |\n| `figure` | `filename`, `label`, `caption` | `width`, `style`, `caption_style` | Centred image with caption |\n| `figure_pair` | `filename1`, `filename2`, `label`, `caption` | `width1`, `width2`, `style`, `caption_style` | Two images side by side |\n| `table` | `rows` (or `header`) | `header`, `widths`, `col_align`, `borders`, `style` | Tabular grid; bold header row, per-column `%` widths and alignment, cell shading, bullets-in-cell |\n\nA `table` takes a list of `rows` (each a list of cell values) and an optional bold `header` row:\n\n```yaml\n- call: table\n  header: [Mês, Vendas, Custos]\n  rows:\n    - [Janeiro, \"10.000\", \"6.000\"]\n    - [Fevereiro, \"12.500\", \"7.200\"]\n  widths: [40, 30, 30]          # optional, % per column, must sum to 100\n  col_align: [left, right, right]  # optional, horizontal align per column\n  borders: true                  # optional, default true\n  style:\n    header_fill: \"#003366\"       # header background\n    header_color: \"#FFFFFF\"      # header text colour (header only)\n    stripe_fill: \"#EEF3FA\"       # zebra background on alternate data rows\n    valign: center               # vertical align of every cell\n```\n\nAll rows must have the same number of cells as the column count. `widths` are percentages of the usable page width (so the table never overflows the margins) and must sum to 100. A cell value with `\\n` becomes a line break inside the cell. Set `borders: false` for a borderless grid.\n\nStyling notes:\n\n- **Shading:** `header_fill` paints the header row, `stripe_fill` zebra-stripes alternate data rows (both accept `#RRGGBB` or `RRGGBB`, off by default).\n- **Header text:** `header_color` colours the header text only (pair it with a dark `header_fill`); the general `color` key paints every cell.\n- **Alignment:** `col_align` overrides alignment per column (great for numbers), `valign` (`top`/`center`/`bottom`) sets the vertical anchor of every cell.\n- **Font:** a table has no font of its own — cells inherit the document **body** font (the same one `call: body` uses), so the table always matches the running text. A document built without a cover template uses the blank `python-docx` theme, whose body font is **Cambria (serif)** while headings are Calibri (sans) — so `body`, `bullet` and the table all render serif there (not a table-specific issue). Set `font_family` on the `table` style to override the table's font only, or on `body`/`bullet`/etc. (or start from a modern cover template) to change the whole body.\n- **Bullets in a cell:** make a cell a `{bullets: [...]}` mapping and each item becomes a bulleted paragraph inside that cell:\n\n  ```yaml\n  rows:\n    - [\"Features\", { bullets: [\"fast\", \"safe\", \"tested\"] }]\n  ```\n\nPainting one specific cell, and merging cells, are not supported yet.\n\nAny section type may appear in either `front_matter` or `sections`. The distinction is only about page numbering. A `toc` is the exception: it is always unnumbered (kept out of the `PAGE` sequence) wherever you place it, so the body always starts at `PAGE 1`.\n\n### Page numbering, three modes\n\n```yaml\n# Mode A: no page numbers anywhere (CVs, one-pagers, fliers)\npage_numbers: false\n\nsections:\n  - call: h1\n    text: Jane Doe\n```\n\n```yaml\n# Mode B: cover/TOC unnumbered, content numbered (reports)\nfront_matter:\n  - call: page_break\n  - call: toc\n\nsections:\n  - call: h1\n    text: Introduction\n```\n\n```yaml\n# Mode C: every page numbered (simple paginated docs)\nsections:\n  - call: h1\n    text: Chapter 1\n```\n\n\u003e [!NOTE]\n\u003e The footer `{total}` placeholder counts the pages of the **numbered body section**, not the whole document, so a report with an unnumbered cover and TOC closes on `N / N` (not `N / N+front-matter`). The body begins on a new page at `PAGE 1`.\n\n\u003e [!NOTE]\n\u003e The legacy flag `hide_page_counter: true` on individual sections is **deprecated**: `build` prints a one-time warning when it sees it, and it is scheduled for removal in v0.5. New documents should use the `front_matter:` block instead.\n\n\u003e [!TIP]\n\u003e Missing image files do not crash the build. A `[IMAGE NOT FOUND: filename]` placeholder is inserted instead, so you can draft the document before all screenshots are ready.\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n\n---\n\n## Styles\n\nVisual properties (font sizes, colors, alignment, spacing, bullet glyph, footer format, and more) are controlled by an optional `styles:` block in `content.yaml`. When the block is absent, the built-in defaults are used.\n\n```yaml\nstyles:\n  h1:     { font_size: 16pt, color: \"#003366\", bold: true }\n  body:   { font_size: 11pt, align: justify }\n  bullet: { glyph: \"→ \" }\n  footer: { format: \"Page {page} of {total}\", align: center }\n\nsections:\n  - call: h1\n    text: Special heading\n    style: { font_size: 20pt }   # inline override wins over the block above\n```\n\nCascade (later wins): built-in defaults, then the `styles:` block, then inline `style:` per section.\n\nFull schema, accepted units, color formats, defaults, and every section type's keys are documented in [`docs/styles-reference.md`](docs/styles-reference.md).\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n\n---\n\n## Project structure\n\n### Repository layout\n\nThe package source tree:\n\n```\n.\n├── docx_builder/\n│   ├── __init__.py\n│   ├── cli/                  # argparse entry package, one module per subcommand\n│   │   ├── __init__.py       # DESCRIPTION + EPILOG + _build_parser() + main()\n│   │   ├── _shared.py        # next-step error printers + resolve_directory()\n│   │   ├── _build.py         # build command (+ --pdf / --open / --no-finalize / --fix-toc-links)\n│   │   ├── _init.py          # init command\n│   │   ├── _export.py        # export pdf command (+ --fix-toc-links)\n│   │   ├── _install.py       # install skill command\n│   │   └── _validate.py      # validate command (em/en dash gate)\n│   ├── builder.py            # build(), init_project(), has_toc()\n│   ├── export.py             # export_pdf() and finalize_source() via Word + JXA (macOS)\n│   ├── toc_links.py          # opt-in PDF ToC-hyperlink repair via PyMuPDF (pdf-links extra)\n│   ├── report.py             # post-build report: words, reading time, em-dash counter\n│   ├── validate.py           # content.yaml prose check: em/en dash \u0026 other AI-tells\n│   ├── scaffold.py           # role-based init scaffolder: layers, idempotence, .gitkeep\n│   ├── elements.py           # paragraph primitives (h1, h2, h3, body, bullet, …)\n│   ├── figure.py             # figure() and figure_pair() with centred captions\n│   ├── pagination.py         # PAGE / NUMPAGES footer\n│   ├── renderer.py           # dispatches content.yaml section calls\n│   ├── styles.py             # StyleResolver + length/color/align parsing\n│   ├── summary.py            # Word TOC field insertion\n│   ├── table.py              # table() builder + border utilities\n│   ├── skill_installer.py    # logic for `docx_builder install skill`\n│   ├── skill/\n│   │   └── SKILL.md          # Claude Code skill, shipped as package data\n│   └── templates/\n│       ├── content.skeleton.yaml      # legacy starter (kept for reference)\n│       ├── default_styles.yaml        # built-in style defaults\n│       └── scaffold/                  # init templates: CLAUDE.md, .gitignore, content shapes, screenshot_intake\n├── docs/\n│   └── styles-reference.md   # full style schema (no-AI manual)\n├── tests/                    # pytest suite\n└── pyproject.toml\n```\n\n### A scaffolded project (`docx_builder init`)\n\n`init` creates a **role-based project** where each directory is a role in the pipeline. The base layout is always created:\n\n```\n.\n├── CLAUDE.md             # context for Claude Code working in this project\n├── .gitignore\n├── report/               # the build: content.yaml renders into output/\n│   ├── content.yaml      #   the document definition (starter, with \"Replace me.\" body)\n│   ├── images/           #   rendered figures referenced by content.yaml\n│   ├── assets/           #   editable figure sources (svg, xlsx, diagrams)\n│   ├── output/           #   generated .docx (and .pdf on macOS)\n│   └── templates/        #   cover .docx templates, if any\n└── .work/                # transient scratch space (gitignored)\n```\n\nOptional layers are added with `--with \u003cnames\u003e` (comma-separated) or all at once with `--full`. Dependencies are auto-resolved (e.g. `monitor` pulls in `tools`):\n\n| Layer | Directory | Role |\n|-------|-----------|------|\n| `brief` | `brief/` | the brief or instructions you are working from |\n| `references` | `references/` | reference and source material you consulted |\n| `src` | `src/` | your work product: code, data, whatever you produce |\n| `meta` | `meta/` | checklist, notes, metadata |\n| `tools` | `tools/` | automation scripts (pulled in by `monitor` and `ai-check`) |\n| `monitor` | `tools/monitor/` | race-safe `screenshot_intake.py` (pulls `tools`) |\n| `ai-check` | `tools/ai-detection/` + `report/ai-check/` | AI-detection drivers, and where their output lands (pulls `tools`) |\n\nEmpty directories get a `.gitkeep`. The scaffolder is **idempotent**: re-running only adds what is missing and never overwrites existing files without `--force`. See [Quick start](#quick-start) for `--name` and `--cover`.\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n\n---\n\n## CLI reference\n\n```text\ndocx_builder --version | -v\ndocx_builder init [DIR] [--full] [--with LAYERS] [--name NAME] [--cover] [--force]\ndocx_builder build [DIR] [--output FILE] [--template-dir DIR] [--no-finalize] [--pdf] [--no-update-source] [--open] [--fix-toc-links]\ndocx_builder validate [DIR] [--strict] [--also FILE...]\ndocx_builder export pdf [DIR] [--input FILE] [--output FILE] [--no-update-source] [--open] [--fix-toc-links]\ndocx_builder install skill [--scope local|global]\n```\n\n- `--version` / `-v` prints the installed version and exits.\n- `DIR` defaults to the current working directory.\n- `init` scaffolds a role-based project (see [Quick start](#quick-start)). `--full` adds every layer plus the embedded `screenshot_intake.py`; `--with a,b,c` adds named optional layers (deps auto-resolved); `--name` sets the project name; `--cover` writes Shape B; `--force` overwrites existing files instead of skipping them. It is idempotent and never clobbers existing files without `--force`.\n- `--output` overrides the YAML `cover.output` and the default pattern (for `build`); for `export pdf` it overrides the destination `.pdf` path.\n- `--template-dir` overrides the template lookup directory.\n- `validate` parses `content.yaml` and scans only the prose fields (`h1`/`h2`/`h3`, `body`, `bullet`, `caption`, `bold_lead`, `reference`), ignoring keys, paths and filenames. It prints each hit with its section, field and position, and exits 1 when any forbidden character is found (0 when clean), so it can gate a pre-commit hook or CI step. Default rules flag em-dash (`U+2014`), horizontal bar (`U+2015`) and figure dash (`U+2012`); `--strict` adds en-dash (`U+2013`). `--also FILE...` scans extra plain-text/markdown files with the same rules.\n- `--no-finalize` (on `build`) skips the Word pass that populates the TOC, keeping `build` pure and fast (useful for CI or scripting on macOS).\n- `--pdf` (on `build`) builds then exports to PDF in one shot. Requires macOS + Microsoft Word.\n- `export pdf` converts a built `.docx` to PDF via Microsoft Word (macOS only). Input defaults to `build`'s filename resolution; `--input` overrides it. The PDF reports its real page count.\n- `--no-update-source` (on `export pdf`, honoured by `build --pdf`) leaves the source `.docx` byte-identical instead of writing back the populated TOC.\n- `--open` opens the result after the command finishes: with `--pdf` both the `.pdf` and the finalised `.docx` (in Word), otherwise the `.docx`. macOS-only; elsewhere it prints a note and skips.\n- `--fix-toc-links` (on `export pdf`, honoured by `build --pdf`) post-processes the PDF to repair ToC hyperlinks that Word's PDF engine shifted. Off by default; needs the optional `pdf-links` extra (`uv tool install 'docx_builder[pdf-links]'`).\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n\n---\n\n## Development\n\nAfter cloning, bootstrap once:\n\n```bash\nuv sync\npre-commit install                       # activates dev-quality on every commit\n```\n\nThen the standard workflow:\n\n```bash\nuv run pytest\nuv run ruff check docx_builder tests\nuv run --with mypy mypy docx_builder\npre-commit run --all-files               # run all dev-quality checkers manually\n```\n\n\u003e [!IMPORTANT]\n\u003e The `pre-commit install` step writes `.git/hooks/pre-commit`. Without it, the hook config in `.pre-commit-config.yaml` is inert and `git commit` bypasses every quality check. Never bypass the hooks with `--no-verify`.\n\nAll features follow **Red, Green, Refactor** TDD. Write a failing test first, implement the minimum code to pass it, then clean up.\n\n\u003cdiv align=\"right\"\u003e\u003ca href=\"#docx_builder\"\u003e↑ Back to top\u003c/a\u003e\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flipex360x%2Fdocx_builder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flipex360x%2Fdocx_builder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flipex360x%2Fdocx_builder/lists"}