A fast CLI tool that generates a table of contents for markdown files — with anchor links compatible with GitHub, GitLab, Bitbucket, or any custom platform. Works out of the box with any git repository.
Generated with tocgenie
Clone and build:
git clone https://github.com/smarkstrife/tocgenie.git
cd tocgenie
npm install
npm run buildInstall globally (run tocgenie from anywhere):
npm install -g .Use as a dev dependency in another project:
npm install --save-dev /path/to/tocgenie# Generate TOC for a single file
tocgenie README.md
# Insert TOC directly into a file (add markers first — see below)
tocgenie --insert README.md
# Generate TOC for all tracked .md files in a git repo
tocgenieGenerate a TOC and print to stdout:
tocgenie README.mdOutput:
- [Installation](#installation)
- [Usage](#usage)
- [Options](#options)
- [Examples](#examples)
- [Contributing](#contributing)
Save the TOC to a separate file:
tocgenie -O toc.md README.mdReal file example — given a file story.md with this structure:
# The Last Compiler
## Prologue
## Chapter 1: The Bug
### The Discovery
### The Aftermath
## Chapter 2: The Fix
## EpilogueRunning:
tocgenie --no-git story.mdProduces:
- [The Last Compiler](#the-last-compiler)
- [Prologue](#prologue)
- [Chapter 1: The Bug](#chapter-1-the-bug)
- [The Discovery](#the-discovery)
- [The Aftermath](#the-aftermath)
- [Chapter 2: The Fix](#chapter-2-the-fix)
- [Epilogue](#epilogue)
Skip the top-level heading and use an ordered list:
tocgenie --no-git --min-level 2 --ordered story.mdOutput:
1. [Prologue](#prologue)
1. [Chapter 1: The Bug](#chapter-1-the-bug)
1. [The Discovery](#the-discovery)
1. [The Aftermath](#the-aftermath)
1. [Chapter 2: The Fix](#chapter-2-the-fix)
1. [Epilogue](#epilogue)
Scan all git-tracked .md files in the current repo:
tocgenieInclude files not yet committed to git:
tocgenie --include-untrackedNot in a git repo? Walk the filesystem instead:
tocgenie --no-git docs/This is the most common workflow. Add two marker comments anywhere in your markdown file:
## Table of Contents
<!-- toc -->
<!-- /toc -->
## IntroductionThen run:
tocgenie --insert README.mdtocgenie replaces everything between the markers with the generated TOC. Re-running the command is safe — it always replaces the existing content, never duplicates it.
Custom marker:
tocgenie --insert --marker "<!-- contents -->" README.mdKeep your TOC up to date automatically. Add tocgenie as a dev dependency and a script in package.json:
{
"scripts": {
"toc": "tocgenie --insert README.md"
},
"devDependencies": {
"tocgenie": "file:../tocgenie"
}
}Then run it as part of your workflow:
npm run tocOr in a GitHub Actions workflow:
- name: Update TOC
run: npx tocgenie --insert README.mdOption 1 — Global install (recommended for personal use):
npm install -g /path/to/tocgenie
tocgenie --insert README.md # works in any directoryOption 2 — Local dev dependency:
npm install --save-dev /path/to/tocgenieAdd to package.json:
"scripts": {
"toc": "tocgenie --insert README.md"
}Option 3 — One-off via node directly:
node /path/to/tocgenie/dist/cli.js --no-git README.md| Flag | Short | Default | Description |
|---|---|---|---|
--flavor <flavor> |
-f |
github |
Anchor flavor: github, gitlab, bitbucket, generic |
--min-level <n> |
1 |
Minimum heading level to include | |
--max-level <n> |
6 |
Maximum heading level to include | |
--ordered |
-o |
false |
Use ordered (1.) list markers |
--no-link |
false |
Omit anchor links (plain text outline) | |
--indent <n> |
2 |
Spaces per indent level | |
--output <file> |
-O |
stdout | Write TOC to a file |
--insert |
-i |
false |
Insert/replace TOC in-place between markers |
--marker <marker> |
<!-- toc --> |
Marker used for in-place insertion | |
--include-untracked |
false |
Include untracked (but not gitignored) files | |
--no-git |
false |
Walk the filesystem instead of using git | |
--anchor-prefix <prefix> |
"" |
Custom prefix for generic flavor |
|
--anchor-strip-regex <regex> |
none | Custom strip regex for generic flavor |
|
[files...] |
all .md |
Explicit files or globs to process |
Different platforms generate anchor slugs differently. Use --flavor to match your target platform.
| Flavor | Example heading | Generated anchor |
|---|---|---|
github (default) |
## My Heading |
#my-heading |
gitlab |
## My Heading |
#my-heading |
bitbucket |
## My Heading |
#markdown-header-my-heading |
generic |
configurable via --anchor-prefix / --anchor-strip-regex |
custom |
Examples:
tocgenie -f gitlab README.md
tocgenie -f bitbucket README.md
tocgenie -f generic --anchor-prefix "section-" README.mdnpm test # run all tests
npm run test:watch # watch mode
npm run build # compile TypeScript
npm run dev -- --no-git README.md # run without buildingsrc/
├── cli.ts Entry point and argument parsing
├── parser.ts Markdown heading extraction
├── anchor.ts Anchor/slug generation per platform flavor
├── toc.ts TOC assembly and in-place insertion
├── git.ts Git-aware and filesystem file discovery
└── types.ts Shared type definitions
tests/
├── parser.test.ts
├── anchor.test.ts
├── toc.test.ts
└── fixtures/ Sample .md files used in tests
Author: Shikhar Srivastava