Skip to content
Agentmart
Submit a tool

migrate4-5

Guides you through migrating markuplint configuration from v4 to v5.

Skill by markuplint

IndexedMIT★ 629
Write a review

Install

Works with Claude Code, Claude apps, Codex, Cursor, Gemini CLI, GitHub Copilot, VS Code, OpenCode, Goose, Windsurf. Read the repository before you give any tool access to your data.

npx agentmarket install skill/markuplint-migrate4-5

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Guides you through migrating markuplint configuration from v4 to v5. Detects current versions, reviews the migration guide, interactively confirms breaking changes and new rules with the user, updates config files and tests. For Claude Code.

Use cases: agent-building, refactoring

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this skill can do and what it asks for, from its SKILL.md. Checked Oct 25, 2026.

Tools
No tools found
Secrets
None asked for
Install scripts
None found

Network hosts it talks to 1

  • codeload.github.com · found in install command

Files it touches

  • ~/.claude/skills/migrate4-5

What's inside

Skill name
migrate4-5
Description
Guides you through migrating markuplint configuration from v4 to v5. Detects current versions, reviews the migration guide, interactively confirms breaking changes and new rules with the user, updates config files and tests. For Claude Code.
License
MIT
Instructions
178 lines in SKILL.md · view on GitHub

Agent Skills spec issues

  • name: "migrate4-5" does not match folder "v4-v5"

Files (1)

  • SKILL.md

SKILL.md (first lines)

# migrate4-5

Guides you through migrating markuplint from **stable v4** (last release `v4.18.3`) to v5. Treat v5 alpha/rc rule names as if they never existed.

Install: `npx skills add markuplint/markuplint@migrations/v4-v5`

## When to Use

Use this skill when the user requests any of the following:

- "Upgrade markuplint to v5"
- "Migrate markuplint from v4 to v5"
- "Update markuplint version"
- "markuplint migration"

## Steps

### 1. Detect Current Versions

- Detect the current versions of markuplint-related packages (`markuplint`, `@markuplint/*`) from `package.json` and list them
- Locate configuration files (`.markuplintrc`, `.markuplintrc.json`, `markuplint.config.js`, etc.)
- Confirm Node.js is **v24.0.0 or later** (v4 documented v18.18.0). Stop and have the user upgrade Node before changing packages.

### 2. Review the Migration Guide

**Documentation base URL**: check the target v5 version with `npx markuplint --version`. If it contains `alpha`, `beta`, or `rc`, use `https://next.markuplint.dev`; otherwise use `https://markuplint.dev`.

- **Website guide (users):** `{base}/docs/migration/v4-to-v5/`

**Required pages:** `{base}/docs/migration/v4-to-v5/` (index), `{base}/docs/migration/v4-to-v5/rules/rule-names` (renames and splits), `{base}/docs/migration/v4-to-v5/aria`, `{base}/docs/migration/v4-to-v5/cli`, `{base}/docs/migration/v4-to-v5/config`

Also fetch when the config uses the feature:

| Topic | Website path |
| --- | --- |
| Framework parsers | `{base}/docs/migration/v4-to-v5/framework` |
| `invalid-attr` split | `{base}/docs/migration/v4-to-v5/rules/invalid-attr` |
| `required-element` | `{base}/docs/migration/v4-to-v5/rules/required-element` |
| `deprecated-element` | `{base}/docs/migration/v4-to-v5/rules/deprecated-element` |
| Table model | `{base}/docs/migration/v4-to-v5/rules/table-row-column-alignment` |
| Parse errors (opt-in) | `{base}/docs/migration/v4-to-v5/rules/parse-error` |
| textlint removal | `{base}/docs/migration/v4-to-v5/rules/textlint` |

Inspect `node_modules` presets and `rule-aliases` only to confirm what the installed v5 actually expands — do not invent names from memory.

Do **not** migrate using `wai-aria-*` intermediate names, `no-unsupported-features`, `script-content`, `srcset-sizes-constraint`, or `input-button-non-empty-value`. Those were not stable v4 rule names.

### 3. Confirm with the User (use AskUserQuestion extensively)

**Always use AskUserQuestion at each decision. Never decide for the user.** Batch up to 4 related questions.

#### Phase 1: Silent gaps and CI (must ask)

These do not produce a deprecation warning:

1. Raw (non-preset) **`permitted-contents`** → add `no-disallowed-ancestor`, `require-ancestor`, `no-duplicate-sibling-attr` to keep v4 coverage?
2. Raw **`no-refer-to-non-existent-id`** → add `no-broken-fragment-link`? (`markuplint:html-standard` alone still lacks this sibling; `a11y` / `recommended` include it.)
3. Raw **`label-has-control`** → add `label-no-multiple-controls`? (`markuplint:a11y` alone does **not** enable the sibling; `html-standard` / `recommended` do.) v5 `label-has-control` only reports a label with **no** associated control.
4. Table-model rules `no-table-cell-overlap`, `no-table-span-overflow`, `no-empty-table-track` escalate **warning → error**. Keep errors, or set `"severity": "warning"` to mimic v4?
5. v4 CI treated warnings as failures? Add **`--no-allow-warnings`** (v5 allows warnings by default).
6. ARIA default is **1.3**. Keep 1.3, or set `ruleCommonSettings.ariaVersion` to `"1.2"`?
7. `wai-aria: true` / `markuplint:a11y` now also run checks that were **off or absent** in v4 `wai-aria` defaults: `no-aria-on-presentational-children`, `no-focusable-in-aria-hidden`, `no-default-aria-value`, `require-parent-role`, `tab-requires-tabpanel`. Keep them, or disable individually?

#### Phase 2: Preset extras on `markuplint:recommended`

v4 `recommended` did not include these; v5 does. Confirm whether to keep or disable:

- `markuplint:compat`: `no-unsupported-browser-features`, `no-nonstandard-features` (needs browserslist for the former; `no-experimental-features` stays opt-in)
- `markuplint:code-styles`: `case-sensitive-attr-name`, `case-sensitive-tag-name`
- `markuplint:security`: `no-event-handler-attr`
- `markuplint:html-standard` now enables `no-unknown-attr` / `no-disallowed-attr` / `no-invalid-attr-value` (v4 `html-standard` did not include `invalid-attr`) and drops `no-duplicate-dt` / `no-ineffective-attr`

#### Phase 3: Other breaking changes that apply

Ask only if the config uses the feature:

- `--config` no longer merges with auto-discovered config
- `extends`: array rule values **replace**; nested `options` are **shallow**-merged
- `required-element` → `require-element`; ghost elements no longer satisfy requirements (`ignoreOmittedElements` default `true`)
- `invalid-attr` `{ type: X }` wrapper removed; route options per the guide
- htmx: `@markuplint/htmx-parser` → `@markuplint/htmx-spec` (drop `parser` entry)
- Alpine: keep parser; spec `@markuplint/alpine-parser/spec` → `@markuplint/alpine-spec`
- `@markuplint/rule-textlint` removed
- pretenders on standard HTML/SVG tags are ignored
- `:closest()` → `:is(… *)` (removed in v6)
- Non-fatal HTML parse errors: opt in via `severity.parseError` (see `rules/parse-error.md`). Off by default.

#### Phase 4: New rules not in any preset

Present opt-in rules (`attr-order`, `class-naming`, … — list from rule-names "no preset" set). For `attr-order`, the user must supply the exact order array; `true` is not enough.

### 4. Update Dependency Versions

- Bump `markuplint` and every `@markuplint/*` to the **same** v5 version
- Uninstall `@markuplint/htmx-parser` / `@markuplint/rule-textlint` if present
- Install `@markuplint/htmx-spec` / `@markuplint/alpine-spec` when those frameworks are in use

### 5. Update Configuration Files

- Rewrite deprecated rule names from Markuplint's deprecation warnings after one run (old names work until v6; still rewrite now)
- Apply the silent-gap siblings the user confirmed
- Set `ruleCommonSettings.ariaVersion` if they chose 1.2
- Disable extra ARIA/preset rules they declined
- Convert `invalid-attr` / `required-element` / framework `parser`/`specs` as agreed
- Named preset groups (`a11y/html-lang`, `a11y/wai-aria/*`, …) can be toggled in `rules` without renaming the user's own nodeRules unless they want names

### 6. Triage newly flagged markup

Everything above is about **config**. Separately, v5 tightened a number of built-in checks so that markup which passed under v4 now fails **with no config change involved** — see [Reference: newly flagged markup](#reference-newly-flagged-markup-no-config-change). Run markuplint once (after step 5) and treat any violation from that list as an expected v5 finding, not a false positive:

- Fix the markup, or
- If a specific case is load-bearing for this project, add a targeted `nodeRules` disable/severity override and note why

Do not silence these by disabling the rule outright — they are spec-conformance checks, not new opt-in preferences.

### 7. Update Tests

- Run markuplint; include `ruleId` and Named Rule Group `name` in assertions when present
- `--config` / `-c` in tests loads **only** that file

From markuplint/markuplint, MIT.

More from markuplint/markuplint

Signals

Stars
629
Forks
70
Open issues
52
Last commit (this folder)
Aug 28, 2026 (2 months ago)
Last release
Oct 21, 2026 (7 days ago)

From GitHub (fetched Oct 24, 2026).

Details

License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from markuplint

Cite this page

migrate4-5 skill. Agent Mart. https://agentmart.dev/skills/markuplint-migrate4-5 (last updated 2026-10-24)