npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@notmanu/annotate

v0.6.0

Published

<div align="center"> <h2>Annotate</h2> <p>Annotate your PDFs with LaTeX & Typst!</p>

Readme

npm version license npm downloads PRs Welcome works on my machine

Demo

Quick Start  •  Features  •  Annotating with AI Agents  •  How it works  •  Examples  •  Contributing

Quick start

1. Install Annotate

# Install globally
npm i -g @notmanu/annotate

# Or with pnpm / bun
pnpm add -g @notmanu/annotate
bun add -g @notmanu/annotate

2. Create a project

Run this command to create a new annotation project and start watching:

annotate homework.pdf --with latex

This creates a homework/ folder, compiles the initial pages, and immediately enters watch mode:

3. Add some annotations!

Edit pages/page-01.tex and add a textbox:

\textbox[x=10em, y=40em, w=30em, h=10em, border]{
  \large
  Hello Annotate!
}

Save the file — Annotate recompiles automatically and updates homework-annotated.pdf.

4. Resume watching

If you close the terminal and come back later:

annotate watch homework/

Features

Write annotations in LaTeX or Typst and overlay them directly onto existing PDFs. Annotate watches your files, recompiles on every save, and produces a final annotated PDF in real time.

Live reload — Edit a .tex or .typ file, save, and see the result instantly. No manual build steps.

Per-page annotations — Each page gets its own file (page-01.tex, page-02.tex, ...) so you only touch what you need.

Automatic page sizing — Overlay pages match the original PDF's dimensions. No configuration required.

Works with your existing tools — Any text editor, any LaTeX packages, any Typst modules. Annotate stays out of your way.

Image generation — Export each page as a PNG with the --images flag. Requires pdftoppm (poppler) or mutool (mupdf) to be installed.

Built-in macros — A generated style.sty / style.typ gives you positioning primitives out of the box.

Supported engines

Annotate works out of the box with your TeX distribution or with Typst.

| Engine | Language | Supported | Tested | Notes | |--------|----------|-----------|--------|-------| | tectonic | LaTeX | | | Recommended, auto-downloads packages | | typst | Typst | | | The future of typesetting! | | latexmk | LaTeX | ✓ | ✗ | Common in TeX distributions | | pdflatex | LaTeX | ✓ | ✗ | Basic LaTeX engine | | xelatex | LaTeX | ✓ | ✗ | Unicode/font support | | lualatex | LaTeX | ✗ | ✗ | Not yet implemented |

Note: Engines that are not tested should work but haven't been verified yet. If you try one, please open an issue and let me know how it goes!

Built-in macros

Every new project includes a style.sty (LaTeX) or style.typ (Typst) with helpful macros so you can start annotating right away.

\textbox (LaTeX) / #textbox (Typst) is the main positioning command. Place a box at any position on the page:

\textbox[x=10em, y=40em, w=30em, h=10em, border]{
  Your annotation here!
}
#textbox(x: 10em, y: 40em, w: 30em, h: 10em, border: true) {
  Your annotation here!
}

| Option | Default | Description | |--------|---------|-------------| | x | 0pt | Horizontal offset from top-left | | y | 0pt | Vertical offset from top-left | | w | 2in | Box width | | h | 0.5in | Box height | | pad | 0pt | Inner padding | | border | off | Show a border (useful for debugging placement) |

Other macros included in the default style:

| Macro | Description | |-------|-------------| | \annotationcolor{color} | Change the annotation text color | | \annotationbox[fill]{content} | Highlighted box (default fill: yellow) | | \annotationlayer{...} | TikZ overlay layer for absolute positioning | | \answerspace[height] | Insert blank space for handwriting (default: 1.2in) | | \begin{defbox}[title] | Definition box environment | | \begin{hintbox}[title] | Hint/note box environment (default title: "Hint") | | definition, theorem, lemma, corollary | Auto-numbered math environments |

Typst equivalents use function syntax: #textbox(x: 10em, y: 40em)[content], #annotation-box(content), #annotation-text("text"), #answer-space(). See style.typ for the full API.

Annotating with AI Agents

Annotate is designed to work well with AI coding agents like Claude Code, Cursor, and Copilot. The workflow is simple: you set up the boxes, the agent fills them in.

1. Set up your project with --agents

The --agents flag generates an AGENTS.md, CLAUDE.md, and automatically enables --images so the agent can see each page:

annotate homework.pdf -w latex --agents

This creates the full agent-ready project structure — img/ holds a PNG per page so the agent can see the layout, and AGENTS.md / CLAUDE.md give it the context it needs.

You can also add --agents to an existing project — it will generate the missing files without overwriting anything:

annotate watch homework/ --agents

2. Place your boxes

Add empty \textbox elements with border enabled where you want the agent to write. The border helps you visually confirm the placement before handing it off:

\textbox[x=150bp, y=350bp, w=330bp, h=120bp, pad=4pt, border]{
  Question 1.
}

\textbox[x=150bp, y=548bp, w=330bp, h=110bp, pad=4pt, border]{
  Question 2.
}

3. Customize the AGENTS.md

The generated AGENTS.md includes sensible defaults for annotation work. Customize it to fit your workflow — this file is automatically picked up by Claude Code and similar tools:

- Prefer `displaystyle` when possible; use `textstyle` only when space is tight.
- Remove the border from a question once it is completed.
- Do not include the question number when writing answers — provide the answer directly.
- Do not attempt to compile the document; it will be compiled automatically.

The agent reads the page images in img/, understands the layout, and fills in the LaTeX — all while Annotate recompiles in the background. See examples/AGENTS.md for a full example.

Automating box placement with OpenCV

For assignments with many printed answer regions, you can skip manual box placement entirely. Let the agent write a quick Python script that detects the boxes from the page image and generates the \textbox coordinates automatically:

# the agent can run this without modifying your project deps
uv run --with opencv-python python detect_boxes.py

The script reads a page image from img/, finds the answer regions using contour detection, and converts the pixel coordinates into \textbox positions using the page dimensions. This is especially useful for worksheets with dozens of small answer boxes or checkbox grids.

How it works

Annotate watches your pages/ directory. When you save a .tex or .typ file, it recompiles only the affected page into a transparent annotation PDF. After compilation, pdf-lib overlays each annotation page onto the corresponding page of the original and writes out the final *-annotated.pdf. The original PDF is never touched.

Examples

The examples/ folder has ready-to-run projects you can use as a reference:

| Folder | Description | |--------|-------------| | examples/latex | LaTeX homework annotation | | examples/typst | Typst homework annotation | | examples/agents | Agent-ready project with AGENTS.md and a full transcript |

Contributing

Found a bug or want to add an engine? Open an issue or send a PR — contributions are welcome.

Dev setup:

bun install

# Link annotate-dev → src/index.ts (runs with Bun, no build step needed)
bun run dev:link

annotate-dev homework.pdf -w latex

# Unlink when done
bun run dev:unlink