Browse Docs pages
Overview
Audit rendered HTML links and local asset references
Source: bones/scripts/rc-links.sh.
Usage
rotkeeper.sh links [options]
Options
--root DIR Rendered directory to scan; defaults to output/
--report FILE Report destination; defaults to bones/reports/link-report-*.md
--json Emit machine-readable JSON to stdout (failures with line+excerpt)
--fix-hint Show suggested fixes for each failure (no auto-fix)
--dry-run Scan without writing a report
--verbose Show detailed logs (line numbers + excerpts)
--help, -h Show this help message
--version, -v Show script version and quit
Examples
bash rotkeeper.sh links # Audit and write report
bash rotkeeper.sh links --fix-hint # Audit with per-failure hints
bash rotkeeper.sh links --json | jq . # Machine-readable output
Exit codes
0 No broken links or missing assets found
1 Broken references found, or audit error
Reads and writes
Environment: reads BONES_DIR, CONFIG_DIR, CONTENT_DIR, DRY_RUN, LOG_DIR, LOG_FILE, OUTPUT_DIR, QUIET, REPORT_DIR, ROOT_DIR, SCRIPT_DIR, TMP_DIR, VERBOSE (canonical via rc-env.sh / rk_load_env); overrides RK_OLIVER_BIN, RK_RENDERER, ROTKEEPER_VERSION when set.
Working directory: No CWD assumption โ all paths are root-relative via ROOT_DIR/BONES_DIR/CONTENT_DIR/etc. derived from rc-env.sh; helpers rk_canonical_path/rk_canonical_or_raw resolve symlinks/portably.
Inputs and outputs: reads rendered HTML under the selected root and audits local href/src targets and anchors, including local asset references. Writes the selected report under the report boundary or emits JSON according to flags; dry-run scans without publishing a report.
Side effects
- delete: removes the bones/tmp scan-result scratch file on exit
- write: mktemp creates a bones/tmp scratch file that captures the Python scan TSV (cleaned up on exit)
- write: creates a bones/tmp scratch file for JSON assembly (deleted below)
- write: serializes the assembled JSON into the scratch file
- delete: removes the JSON scratch file before failing
- write: appends the JSON report to the per-run log under bones/logs
- delete: removes the JSON scratch file after emit
- write: overwrites the link-audit markdown report
- write: overwrites the link-audit markdown report
Notes
Design
The command runs an embedded Python 3 HTML parser over .html files under
the selected output root. It checks anchor href attributes and src
attributes on scripts, images, sources, video, and audio.
URLs are split before percent decoding, so encoded # and ? remain part
of a filename. Directory targets resolve to index.html. Canonical target
paths must remain inside the selected scan root. Failure records include
the source page, target, reason, line number, and an excerpt.
Limits
The command does not fetch external URLs or validate CSS imports, stylesheet
link elements, srcset, or references generated by JavaScript.
It validates a fragment only for an anchor-only URL in the same page.
For other.html#fragment, it checks the file, not the destination fragment.
Files that cannot be read are skipped. A successful result covers only the
references the parser collected.
The scan root must resolve under OUTPUT_DIR. Selecting a narrower root
also makes links outside that subtree failures, even if they stay inside
the overall output tree.
Cautions
--report is not boundary-checked despite the script header's report-boundary
description. Relative report paths resolve from ROOT_DIR; the command
creates parent directories and overwrites an existing report.
JSON mode also writes a short Markdown summary unless --dry-run is active.
--fix-hint suggests changes; it does not change pages.
Put shared flags such as --dry-run before command-specific options.
The shared parser stops at the first unrecognized option. Dry-run scans
normally and writes bootstrap logs and temporary results, but does not
publish a report. Its result scratch file is removed on exit.
History
[0.5.0] - 2026-07-23
- Added dispatcher link audit tool (
rc-links.sh/./rotkeeper.sh links) for link checking and local asset verification with angle-bracket compatibility.