QuickOutline, editing PDF bookmarks from a table of contents
给PDF添加大纲、目录。 Add or edit outline/contents/bookmark to PDF
At a glance
- What is it?
- QuickOutline is a desktop tool that writes a text table of contents into a PDF as real bookmarks, and exports existing bookmarks back out as text. It is useful for ebooks, textbooks and papers whose contents page never made it into the file, and it does no OCR at all.
- Who is it for?
- QuickOutline suits someone with a long text PDF whose bookmarks are missing or wrong, who is willing to paste a contents list and set a page offset by hand. It does not suit a workflow of scanned documents, since the project states plainly that it does not support OCR, and it does not suit a team that needs batch processing of thousands of files, because the primary interface is a desktop application even though a command line interface exists.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 12 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The PDF has pages but no bookmark tree
A PDF is a page-oriented format with an optional outline structure attached. That optional part is the problem this tool addresses. Plenty of PDFs in the wild have no bookmarks at all, or have bookmarks pointing at the wrong pages, or have a table of contents printed on page two that nobody has turned into navigation.
QuickOutline is a desktop tool focused on PDF outline and bookmark editing. It can write a text table of contents into a PDF, and it can export directory text from bookmarks that already exist in a PDF. The stated use is tidying up ebooks, textbooks, papers and long documents.
The design decision that makes it usable is that the input is plain text, not a structured format. You paste a table of contents, the tool parses it into a hierarchy, and it writes that hierarchy into the file as PDF bookmarks. Nothing has to be re-typed per entry, and the same text can be reused for another document.
The feature list in the project documentation covers adding, editing and exporting outline bookmarks, parsing directory text either by sequence number or by indentation, page offset support for when PDF page numbers do not match the book's printed page numbers, a setting for the zoom mode used when a bookmark jumps, two-way editing between a text view and a tree view, loading a table of contents from existing PDF bookmarks, extracting a table of contents from a text-based PDF as a reference, page label support, command line import and export, Windows, macOS and Linux support, and a Chinese or English interface where a Chinese system locale defaults to Chinese and other locales default to English.
The audience is a reader or editor with a stack of PDFs and a contents list, not a developer building a document pipeline.
Two ways to parse a table of contents
The hierarchy detection is where the interesting engineering sits, because a table of contents in the wild comes in two shapes and the tool supports both.
The first is by sequence number. The project documentation shows a three-level example where each line starts with a dotted number, and the hierarchy is derived from that numbering. The documentation notes that after the outline is written into the PDF, the sequence numbers in the titles are preserved, which matters if your source text has them.
The second is by indentation. Here the level is derived from how far the line is indented, and the documentation recommends using tabs or uniform-width spaces. This is the method for contents lists that have no numbering, which in a textbook is at least as common as the numbered kind.
The command line exposes the choice directly. The `--method` parameter takes `seq` or `indent`, and defaults to `seq`.
quickoutline outline import \
--pdf input.pdf \
--outline toc.txt \
--output output.pdf \
--offset 0 \
--method seq \
--view-mode noneThere is also an automatic indentation feature that tidies the hierarchy from the numbering and formats the title and page number. The documentation shows a mangled line, a chapter marker with the title and the page number run together, and the tidied result with spaces separating the three parts. The caveat is that the Chinese sequence recognition covers common forms only, things like chapter, section and part markers, so an unusual numbering scheme is not recognized and the line is left alone.
That is a fair summary of the whole approach. The parser handles the common cases well and leaves the uncommon ones untouched rather than guessing, and a user who needs something stranger can still edit the text by hand before pasting it in.
Page offset is the setting you will actually argue about
Page numbers are where this kind of tool lives or dies, and QuickOutline handles the mismatch explicitly.
The offset is defined as the PDF page number minus the original book's page number. The documentation gives the example: if the table of contents in the original book says page 1 but that content is actually on page 12 of the PDF, then the offset is 12 minus 1, which is 11.
12 - 1 = 11When adding an outline, QuickOutline adds the offset to the page numbers found in the directory text. The offset supports negative values, but the result after the addition has to stay within the actual page range of the PDF, which is a sensible guard against pointing a bookmark past the end of the file.
The same offset parameter exists on the export side, so you can pull bookmarks out of a PDF and shift the page numbers back to the printed-book numbering. That symmetry is what makes the tool useful for round-tripping rather than only for one direction.
The zoom mode is the other setting that affects the result. The `--view-mode` parameter defaults to `none` and takes a fixed set of values.
none
fit-to-page
fit-to-width
fit-to-height
fit-to-box
actual-sizeThis is what the reader's view does when they follow a bookmark. For a technical manual where a diagram is referenced, fit-to-width or fit-to-page is often the right choice, and for a text document actual-size is the least surprising. The default of none leaves the reader's current zoom alone.
The point worth flagging is that the offset is a single number for the whole document. A book whose front matter is numbered in roman and whose body restarts at 1 will not be served by one offset, and the documentation does not describe a way to set it per entry.
The CLI can import and export, and the desktop app can do more
There are two front ends, and the documentation is clear about which is which.
The command line is available after installing the desktop application, and the `quickoutline` command handles directory import and export. The shortest form takes the PDF and the outline file.
quickoutline outline import --pdf input.pdf --outline toc.txtThe export side is the mirror image.
quickoutline outline export --pdf input.pdfWith the longer forms shown, the output paths become explicit, and the export form documents the `--offset` parameter for applying a page offset while exporting.
quickoutline outline export \
--pdf input.pdf \
--output outline.txt \
--offset 0Two defaults are worth noting. On import, leaving `--output` unset generates a file named `*_new.pdf`, so the original is not overwritten. On export, leaving `--output` unset generates `*_outline.txt`. Both are sensible, and both mean the tool will not destroy your input by accident.
The desktop application has capabilities the CLI does not expose, and the documentation lists them. There is a text view and a tree view that edit in both directions, so you can restructure the hierarchy in a tree and see the text change, or paste new text and see the tree rebuild. There is a built-in table of contents extraction feature for text-based PDFs, which gives you a starting point to paste and clean up. There is support for page labels, which is the mechanism a PDF uses to display a page number that differs from the physical page index, and the offset feature operates against that labeling.
For a first real use, the documented desktop flow is five steps: choose or drag in the PDF file, type or paste the table of contents into the directory text area, set the page offset as PDF page minus book page, choose the parse method and the zoom mode, then add the outline and save the PDF.
No OCR means the hard cases stay unsolved
There is one limitation the project states up front, and it is worth reading before you download anything: QuickOutline does not support OCR. Scanned or image-based PDFs need text extracted first using the system OCR, PowerToys, dedicated OCR software or another tool.
That is a real boundary, and it cuts out the case where a book was scanned and the contents page is an image. The tool cannot read it, and it will not try.
What the tool does offer is a partial path around it. The documentation lists the ways to get a table of contents text: load the bookmarks if the PDF already has them, try the built-in TOC extraction on a text-based PDF, copy the contents from a publisher, a review site or a store page, or use an AI or OCR tool to recognise the table of contents text and then paste the result into QuickOutline to tidy it up.
So the workflow for a scanned document is a pipeline, not a single tool: get the text out by some other means, then let QuickOutline handle the part it is good at, which is turning text into a bookmark tree with correct page targets.
There is a second limitation in the same area. Because the offset is one number for the whole document, a book with roman-numbered front matter followed by a body that restarts at page 1 needs either two passes or a hand-edited outline. The documentation does not describe per-entry offsets, so that is a workaround you assemble rather than a feature you configure.
A Tauri and Svelte desktop app, with a Rust core
The repository layout tells you the current architecture, and it is a full rewrite in progress rather than a small utility.
The top-level entries include a `src/` directory for the Svelte front end, a `src-tauri/` directory for the Tauri shell, a `server/` directory, a `crates/` directory, `packages/` with workspaces for `packages/document/*` and `packages/shared-kit`, a `legacy/` directory, `messages/` for internationalization, `dev_notes/`, `scripts/`, `tests/`, a `public/` directory, and a `project.inlang/` directory for translation tooling.
The Cargo workspace is small and explicit.
[workspace]
members = ["crates/core", "src-tauri"]
exclude = ["services/miniapp-api"]
resolver = "3"Two members, the core crate and the Tauri application, with a separate service excluded from the workspace. The Rust core is where the PDF manipulation and the outline parsing live, and the JavaScript package manifest shows the front end side: the project is named `quickoutline` at version `3.0.0-pre`, uses bun as its package manager at `[email protected]`, and the build script assembles assets and then runs vite.
"build": "bun run copy:assets && bun run build:outline-parser-cli && vite build",The `copy:assets` step pulls in KaTeX, Paged.js and PDF.js, which is a useful signal about the feature set: KaTeX for formula rendering, Paged.js for pagination, and PDF.js for reading and previewing the document. The `build:outline-parser-cli` step is the piece that produces the command line binary from the shared parsing code, which is why the CLI and the desktop app cannot disagree about how a table of contents is parsed.
The dependency list is heavy on CodeMirror and Milkdown, which are rich text and code editors used for the directory text area, and the `check` script runs `svelte-check` for type checking.
The licence is AGPL-3.0, which is the one to think about hardest. The AGPL's copyleft reaches networked use, so if you modify the tool and run a modified version as a service, you owe source to users. For a desktop application you install locally, the effect is much smaller, but it is a different licence from the permissive MIT and Apache grants most of these projects carry, and it is the reason to read the terms rather than assume them.
Editorial conclusion
QuickOutline suits someone with a long text PDF whose bookmarks are missing or wrong, who is willing to paste a contents list and set a page offset by hand. It does not suit a workflow of scanned documents, since the project states plainly that it does not support OCR, and it does not suit a team that needs batch processing of thousands of files, because the primary interface is a desktop application even though a command line interface exists. Verify first that the page offset you compute lands each entry on the right page in a sample of the document, that the parse method you choose matches the shape of your table of contents, and that the licence terms of the AGPL-3.0 grant fit how you intend to distribute the tool.
Frequently asked questions
What does QuickOutline do with a PDF?
It adds, edits and exports outline bookmarks. You can write a text table of contents into a PDF as real bookmarks, load a table of contents from bookmarks a PDF already has, extract a table of contents from a text-based PDF as a reference, and export existing bookmarks back out as text.
Does QuickOutline support OCR for scanned PDFs?
No. The project states that QuickOutline does not support OCR, and that scanned or image-based PDFs need text extracted first using the system OCR, PowerToys, dedicated OCR software or another tool. You can use an AI or OCR tool to recognise the table of contents text and paste the result into QuickOutline to tidy it up.
How does the page offset work in QuickOutline?
The offset is the PDF page number minus the original book's page number, so if the book's table of contents says page 1 but the content is on PDF page 12, the offset is 11. It supports negative values, and the result after adding must stay within the PDF's actual page range.
How do I import a table of contents from the command line?
Run quickoutline outline import --pdf input.pdf --outline toc.txt, adding --output, --offset, --method and --view-mode for full control. The --method parameter takes seq or indent and defaults to seq, and leaving --output unset generates a file named *_new.pdf rather than overwriting the original.
What licence is QuickOutline released under?
AGPL-3.0, with the LICENSE file at the top of the repository. The AGPL reaches networked use, so a modified version offered as a service carries source disclosure obligations, and that is worth checking against how you intend to use the tool.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/ririv-quickoutline)Was this useful?