Skip to content

Add gitbook content commands: lint, format, broken-links#1231

Draft
gregberge wants to merge 6 commits into
mainfrom
greg/rnd-11627-improve-local-markdowngit-experience-with-clis-and-other
Draft

Add gitbook content commands: lint, format, broken-links#1231
gregberge wants to merge 6 commits into
mainfrom
greg/rnd-11627-improve-local-markdowngit-experience-with-clis-and-other

Conversation

@gregberge

@gregberge gregberge commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

What

New gitbook content command group (RND-11627), bringing GitBook's own content pipeline to local markdown/git workflows:

gitbook content lint docs/                    # content GitBook would remove/restructure + invalid frontmatter
gitbook content broken-links docs/            # broken internal links & anchors (platform-exact section ids)
gitbook content format --write docs/          # apply canonical style, never alters content
gitbook content format --write --force docs/  # full normalization (exactly what GitSync commits)

The heavy lifting is @gitbook/content (companion PR: GitbookIO/gitbook-x#23807), which embeds the platform's parser, normalization and serialization — so lint reports what will actually happen on import, format output is byte-identical to GitSync exports, and anchors are validated with the same section-id algorithm the renderer uses.

Design decisions:

  • lint and format have strict separate responsibilities: style is format's job (diffs shown, --write fixes), content changes are lint's job (errors with explicit messages like "This content will be removed because it is not supported by GitBook"). format never applies content-altering changes unless --force.
  • The engine is an ESM-only bundle, so the CLI is now ESM: "type": "module", esbuild --format=esm with a small banner shimming require/__dirname for bundled CJS deps and the cloudflared path, bin shim uses import, postinstall.jspostinstall.cjs.
  • The engine is bundled into dist/cli.js at build time but loaded lazily, so gitbook dev/auth/etc. keep their startup time.
  • Exit codes are CI-friendly: errors fail, warnings only with --strict, format (check mode) fails when files need formatting.

⚠️ POC state

@gitbook/content is consumed via a file: dependency on a local gitbook-x checkout — CI will be red until the engine is published to npm. Draft until then.

Tested

  • bun run build, tsc --noEmit, prettier clean.
  • ESM runtime verified: --help, whoami (conf/ora/api stack), and all three content commands end-to-end (lint error → safe format preserves content → --force → lint clean).
  • E2E on a real docs repo (81 files): found 2 genuine broken anchors, zero false positives.
  • Not exercised: gitbook dev/check runtime (esbuild/miniflare externals import fine under ESM interop, but the dev-server path deserves a manual run before merging).

🤖 Generated with Claude Code

New command group in @gitbook/cli powered by @gitbook/content-engine
(the platform's own parser/normalizer/serializer, bundled at build time):

- gitbook content lint: reports content GitBook would remove or
  restructure on import, and invalid frontmatter. Style is not lint's
  concern.
- gitbook content format [--write] [--force]: applies GitBook's
  canonical style; never alters content unless --force, which applies
  the full normalization (exactly what GitSync commits back).
- gitbook content broken-links: checks internal links and anchors
  across markdown files, using the platform's section-id algorithm.

The engine is loaded lazily so other commands keep their startup time.
It is consumed via a file: dependency for now; switching to the npm
package once @gitbook/content-engine is published.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 087eaeb

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

gregberge and others added 5 commits July 5, 2026 21:21
The content-engine is now built as a self-contained ESM bundle (tsdown),
so the CLI bundle switches to ESM output:

- package.json: type module, postinstall script renamed to .cjs
- build.sh: esm format, with a banner shimming require/__dirname for
  bundled CommonJS dependencies and the cloudflared tunnel path
- cli.js bin shim: import instead of require

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
GitBook parses SUMMARY.md as navigation, not as a page; page-level
lint/format do not apply. broken-links keeps checking it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When the repository declares a .gitbook.yaml, the content commands
interpret it like Git Sync does:

- lint/format default to the configured content root, so files outside
  it (e.g. the GitHub-facing README.md) are not treated as GitBook
  content, and skip the configured structure.summary file instead of a
  hardcoded SUMMARY.md.
- broken-links resolves pages and root-relative links against the
  configured root, and keeps checking the table of contents.

Repositories without a .gitbook.yaml behave as before.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The content package was renamed in gitbook-x; update the file:
dependency path and the imports in the content commands.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant