# remark: a markdown processor you build from plugins

> remark turns markdown into an mdast syntax tree that plugins inspect and rewrite. It is a toolkit for pipelines, not a formatter, and the README points anyone who only wants HTML at micromark instead.

**remarkjs/remark** — markdown processor powered by plugins part of the @unifiedjs collective

- Repository: https://github.com/remarkjs/remark
- Website: https://remark.js.org
- Stars: 9,010 · Forks: 387
- Language: JavaScript
- License: MIT
- Published: 2026-09-21 · Updated: 2026-09-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/remarkjs-remark

## The problem remark solves is markdown as data, not markdown as text

Most markdown tools take a string and give you a string or HTML back. remark takes markdown and gives you a tree. The README describes it as "an ecosystem of plugins that work with markdown as structured data, specifically ASTs (abstract syntax trees)", and that single decision is what the rest of the project follows from. Once the document is a tree, a plugin can walk it, count headings, rewrite link targets, insert a table of contents, or reject a construct it does not like. The target audience is therefore developers writing tooling: documentation pipelines, static site generators, linters, and migration scripts that need to change hundreds of files consistently. The README states the project is 100% compliant with CommonMark, and 100% with GFM or MDX when the matching plugin is added. Note the phrasing: compliance with GFM is a plugin property, not a default. If you install remark and parse a table, you get what CommonMark gives you, which is not a table.

## remark-parse, mdast, remark-stringify: the data flow

The monorepo contains four packages, and the README explains what each is for. remark-parse takes markdown and produces mdast, the markdown syntax tree. remark-stringify takes mdast and produces markdown. The remark package bundles unified, remark-parse and remark-stringify for the case where both input and output are markdown. remark-cli wraps remark for inspecting and formatting files from a shell. The engine underneath is unified, which the README calls "the core project that transforms content with ASTs"; remark is the part that adds markdown support to it. A pipeline is assembled by chaining .use() calls, and each plugin receives the tree and may return a new one. The README's own example of a custom plugin walks the tree with visit from unist-util-visit and increments node.depth on every node whose type is 'heading', which turns a level one heading into a level two heading. That is the whole extension model in miniature: no parser changes, no regexes over raw text, just a typed node and a mutation. Plugins that change syntax rather than the tree, such as remark-gfm, hook in at the parsing layer instead, which is why the README distinguishes plugins that extend syntax, inspect trees, change trees, and transform to other syntax trees.

## Installing remark and running a first pipeline

The README does not give an install command, but the packages are published under the names used in its import examples. The combined package is what you want when markdown goes in and markdown comes out.

```bash
npm install remark
```

The README's markdown-to-markdown example imports remark-parse, remark-stringify and unified separately, so a minimal script that parses and reprints a document looks like this. Run it and the console should print the same heading text back, because no plugin has changed the tree yet.

```js
import remarkParse from 'remark-parse'
import remarkStringify from 'remark-stringify'
import {unified} from 'unified'

const file = await unified()
  .use(remarkParse)
  .use(remarkStringify)
  .process('# Hello, *Mercury*!')

console.log(String(file))
```

To make the pipeline do something, add a plugin between parse and stringify. The README shows a plugin that raises every heading by one level, using visit to find heading nodes and node.depth++ to change them.

```js
import remarkParse from 'remark-parse'
import remarkStringify from 'remark-stringify'
import {unified} from 'unified'
import {visit} from 'unist-util-visit'

function myRemarkPluginToIncreaseHeadings() {
  return function (tree) {
    visit(tree, function (node) {
      if (node.type === 'heading') {
        node.depth++
      }
    })
  }
}
```

The README states the output for the input '# Hi, Saturn!' is '## Hi, Saturn!'. For command line use there is remark-cli, and the repository's own format script invokes it as ./packages/remark-cli/cli.js --frail --output --quiet -- . , which shows the flags in real use: --frail makes warnings fail the run, --output writes fixes back to the files, and the trailing dot is the path being processed.

## Where remark is the wrong tool

The README answers this directly, which is unusual and worth respecting: "If you just want to turn markdown into HTML (with maybe a few extensions), we recommend micromark instead." That is the honest boundary. remark exists to be extended, and the cost of that flexibility is a dependency tree and a pipeline you have to assemble. If your requirement is a function that takes a string of markdown and returns a string of HTML with no further processing, you are paying for machinery you will not use. The README offers a second escape hatch for the opposite case: if you do not use plugins and want to work with syntax trees manually, use mdast-util-from-markdown and mdast-util-to-markdown. There is also a supply chain caveat the README raises itself. Anyone can publish a remark plugin, and the project says to "carefully assess the quality of remark plugins too" when deciding what to depend on. The 150+ plugins are not a curated set; some live in the @remarkjs organization and others do not. A plugin that has not been updated since an mdast version change is a real failure mode, and the README does not document any compatibility shim for that.

## remark-rehype versus micromark: two ways to reach HTML

The closest alternative for the HTML use case is micromark, which the README recommends for that job. The difference is architectural. micromark is a markdown parser that produces HTML directly, with extensions for GFM and MDX, and no tree in between that you are expected to touch. remark goes through mdast, so reaching HTML means adding remark-rehype to convert the mdast tree into a hast tree and then a serializer such as rehype-stringify to print it. The README's own example chains remarkParse, remarkRehype, rehypeSanitize and rehypeStringify, with the sanitize step sitting between the two trees. That extra hop is exactly what makes remark worth using on a documentation site: because there is a tree, you can run rehype-sanitize over untrusted content before serialization, which a direct parser-to-HTML path does not give you as a separate stage. If you never need that stage, micromark is the shorter route, and the project says so.

## Licence, releases and what upgrading costs

The repository is MIT licensed, and the root package.json repeats that with "license": "MIT". The packages are published independently rather than as one versioned unit, which is visible in the release history: remark-cli@12.0.1 was released on 2024-04-30, while the 15.0.0 and 15.0.1 releases for the core package landed on 2023-09-18. That means an upgrade is rarely a single version bump. You are tracking remark, remark-parse, remark-stringify, remark-cli and each plugin separately, and a plugin that pins an older mdast major version can hold you back. The last push to the repository was on 2026-09-01. The MIT licence lets you use, modify and redistribute the code, including in closed products, provided the copyright notice and permission notice are kept; that is the general shape of the licence and not legal advice, so read the license file in the repository if the distinction matters to you.

## Conclusion

Adopt remark when you need to inspect or rewrite markdown as data: lint rules, heading shifts, generated tables of contents, or markdown to HTML in a pipeline you control. Do not adopt it if you only want markdown rendered to HTML once, since the README recommends micromark for that. Before committing, check that the plugin you plan to use is maintained by someone you trust, because anyone can publish one, and confirm whether you need remark-parse and remark-stringify alone or the combined remark package.

## FAQ

### How do I install remark-gfm?

The README lists remark-gfm as the plugin that adds GFM support, and states that remark is 100% compliant with GFM once that plugin is added. It is installed from the same registry as the other packages and added to the pipeline with .use() between parsing and stringifying.

### What is the difference between remark and rehype?

They are separate ecosystems for separate input formats. remark works on markdown and uses the mdast tree; rehype works on HTML and uses hast. The README joins them with remark-rehype, which converts a markdown tree into an HTML tree so an HTML plugin such as rehype-sanitize can run on it.

### What is remark used for?

The README describes remark as a tool that transforms markdown with plugins, where plugins inspect and change the markup. Typical uses in its examples are turning markdown into HTML, adding GFM and frontmatter support, checking markdown, and formatting markdown files from the command line.

### Do I need remark if I only want to render markdown as HTML?

The README recommends micromark instead when you just want to turn markdown into HTML, possibly with a few extensions. remark is aimed at cases where you need to inspect or change the tree, or where you want to combine markdown and HTML plugins.

### Can I write my own remark plugin?

Yes. The README shows a plugin as a function that returns a function receiving the tree, then uses visit from unist-util-visit to find nodes and mutate them, for example incrementing node.depth on headings. Plugins that change syntax instead of the tree hook in at the parsing layer.

## Sources

- [License: MIT](https://github.com/remarkjs/remark/blob/main/LICENSE)
- [Project website](https://remark.js.org)
- [README](https://github.com/remarkjs/remark/blob/main/README.md)
- [Releases](https://github.com/remarkjs/remark/releases)
- [remarkjs/remark on GitHub](https://github.com/remarkjs/remark)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/remarkjs-remark
