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

checkpointer

v0.3.0

Published

Git-isolated checkpoints that humans and AI agents share — save working states, revert anytime, ship a range as one clean commit, and map your TypeScript/JavaScript or Java call graph in the browser.

Downloads

889

Readme

checkpointer

Git-isolated checkpoints that humans and AI agents share — save working states, revert anytime, ship a range as one clean commit, and map your TypeScript/JavaScript or Java call graph in the browser.

When you (or an AI agent) work through a long task, you want save points: a way to mark "this works", roll back when something breaks, and at the end turn all that churn into one clean commit. checkpointer does exactly that, in a shadow git repo kept outside your project — so your real git log stays clean until you ship.

  • Shared by humans and agents — same commands, same checkpoints. Works with Claude Code, Cursor, or any tool that can run a shell command.
  • Isolated from your repo — checkpoints live in ~/.checkpointer, never in your project's .git. Nothing shows up in git log until you ship.
  • Captures everything — unlike editor undo, it snapshots the whole working tree, including files changed by scripts, formatters, and codemods.
  • Ships to one commit — bundle a range of checkpoints into a single commit on your branch, then push when you're ready.
  • Maps your codecheckpointer graph opens an interactive, searchable function call-graph of your TypeScript/JavaScript or Java project in the browser, so you can see how functions reach each other before you change them. Polyglot repos render as one combined graph. Fully offline.

Install

npm install -g checkpointer      # then: checkpointer <command>
npx checkpointer <command>       # or run without installing

Requires Node 18+ and git. Also available as ckpt.

Without npm (git clone)

If you can't access the npm registry, clone the repo — dist/cli.js is committed and is a single self-contained bundle with no runtime dependencies:

git clone https://git.soma.salesforce.com/v-akshay/checkpointer.git
cd checkpointer
node dist/cli.js --help

To use it like a regular command (ckpt) without typing node dist/cli.js every time:

# macOS / Linux — copy to somewhere on your PATH
sudo cp dist/cli.js /usr/local/bin/ckpt
sudo chmod +x /usr/local/bin/ckpt
ckpt --help

# or add the dist folder to your PATH in ~/.zshrc / ~/.bashrc
export PATH="$PATH:/path/to/checkpointer/dist"
alias ckpt="node /path/to/checkpointer/dist/cli.js"

Then cd into any git project and start checkpointing:

cd ~/my-project
node /path/to/checkpointer/dist/cli.js init   # or just: ckpt init

To rebuild from source (only needed if you edit the TypeScript):

npm install   # installs tsup + typescript — dev tooling only
npm run build

Quick start

checkpointer init                              # set up checkpointing here
checkpointer save before-refactor              # snapshot before risky work
# ... make changes ...
checkpointer save working --status working     # mark a known-good state
checkpointer restore before-refactor           # something broke? roll back
checkpointer ship -m "Refactor auth module"    # bundle it all into one commit
git push                                        # ship never pushes — you do

Concepts

  • Checkpoint — a full snapshot of your working tree at a moment in time, with a name, a status, and (optionally) who made it and why.
  • Statusworking (verified good), wip (in progress, the default), or broken (known bad). ship refuses to include broken checkpoints unless forced.
  • Shipping — replaying the state of a chosen checkpoint onto your real repo as a single commit. Everything since the last ship is bundled together.
  • Shadow repo — a hidden git repository per project under ~/.checkpointer. It is how snapshots are stored cheaply; it never touches your project's .git.

Commands

| Command | What it does | | --- | --- | | init | Initialize checkpointing for the current project | | save [name] | Snapshot the working tree (auto-names cp-N if no name) | | list (ls) | List all checkpoints | | status | Show how many checkpoints are waiting to be shipped | | changed [id] | Probe whether the working tree differs from a checkpoint (exit 100 if not) | | show <id> | Show a checkpoint's details and tracked files | | diff <a> [b] | Diff two checkpoints, or one checkpoint vs current files | | restore <id> | Reset the working tree to a checkpoint (auto-saves first) | | tag <id> <status> | Mark a checkpoint working, wip, or broken | | ship | Bundle unshipped checkpoints into one commit on your repo | | graph | Visualize the project's functions and call graph in your browser | | info | Show where checkpoints are stored and which paths are excluded | | skill install | Install the Claude Code skill so agents know how to use this |

Reference any checkpoint by name (login), sequence (#4), or short sha. Run checkpointer <command> --help for full options and examples.

Machine-readable output (--json)

Add --json to any command for a stable, versioned envelope on stdout:

// success
{ "schema": "checkpointer/v1", "ok": true,  "data": { /* command payload */ } }
// failure (also exits non-zero)
{ "schema": "checkpointer/v1", "ok": false, "error": { "message": "...", "code": "..." } }

Branch on ok (and on the exit code) rather than parsing prose. Fields inside data are additive; schema only changes on a breaking envelope change.

Exit codes

Commands exit 0 on success. On failure the exit code is stable and tells you why, so scripts and agents can react without parsing the message:

| Code | Meaning | Examples | | --- | --- | --- | | 1 | generic / unexpected | a git plumbing failure | | 3 | environment not ready | not initialized, not a git repo, lock held, corrupt metadata | | 4 | bad input | no such checkpoint, duplicate name, invalid status, missing message | | 5 | safety refusal — a human decision is needed | shipping a broken checkpoint without --force; shipping onto a detached HEAD; shipping a checkpoint a restore set aside | | 6 | benign no-op — nothing to do | nothing unshipped, repo already matches the checkpoint |

Key options

checkpointer save v1 --status working -m "first working version"
checkpointer save --intent "extracting the parser"     # record why (for agents)

checkpointer ship --dry-run                            # preview what will commit
checkpointer ship --upto v1 -m "Ship first version"    # ship up to a checkpoint
checkpointer ship --force -m "..."                     # include broken checkpoints

Safety

  • Restore can't lose work. Every restore first auto-saves your current state, so you can always restore that to undo. These auto checkpoints are marked and don't count toward what gets shipped. Restoring an earlier checkpoint never deletes the later ones — they stay in list so you can jump straight back to them; they are only "set aside" (marked under a divider) so a later ship won't bundle the line of work you rolled away from.
  • Ship follows the live line of work. ship defaults to the latest checkpoint a restore hasn't set aside, and refuses an explicit --upto on a set-aside one — so after a rollback it always commits the tree you're actually on, never a stale or abandoned snapshot. To ship set-aside content, restore it (or save your current state) first, which makes it live again.
  • Ship only adds a commit. ship builds the commit from a checkpoint's snapshot using git plumbing — it never resets your working tree, so uncommitted edits and untracked files are left exactly as they were.
  • Secrets stay put. .env, *.pem, *.key, secrets.*, node_modules, and your .git are never snapshotted — so a restore never overwrites them. See checkpointer info for the full list; add your own patterns in the shown ignore file.
  • Saving is idempotent. A plain save with nothing changed reuses the latest checkpoint instead of creating an empty duplicate, so saving often is cheap. Pass --allow-empty (or a name/message/status) to force a checkpoint anyway.
  • Nested git repos are skipped, not silently broken. A submodule or accidental inner repo can't be snapshotted faithfully, so checkpointer warns and skips it (listing it in nestedRepos under --json) rather than recording a dangling pointer. The directory is left on disk untouched; a restore simply won't recreate it.
  • Nothing leaves your machine. No telemetry. Checkpoints are local git objects.

Visualizing your code (graph)

Debugging an unfamiliar codebase is easier when you can see how functions call each other. checkpointer graph parses your TypeScript/JavaScript or Java project (so calls resolve accurately — methods, this., inheritance, and imports, not just name matches) and opens an interactive map in your browser:

checkpointer graph                  # analyze + serve on localhost + open the browser
checkpointer graph --no-open        # just print the localhost URL
checkpointer graph --out graph.html # write a standalone, shareable HTML file
checkpointer graph --json           # emit the raw graph (nodes, edges, roots)
checkpointer graph --root ../other  # analyze a different project

In the viewer you can:

  • Read top-down from each entrypoint (a "root" — a function nothing in the project calls) and click any function to expand what it calls, drilling as deep as you like.
  • Search any function by name or file; jump straight to it.
  • Focus a function to see its ancestors (everyone who reaches it, up to the entrypoints) beside its descendants (everything it calls) — both expandable.
  • See each function's full signature with type-checker-resolved parameter and return types — so you learn what it takes and returns even when there's no comment — alongside its description, a per-parameter table (name, type, optional, JSDoc @param prose when present), kind (function/method/constructor), async flag, and file:line, with recursion and cycles flagged inline.
  • Hit "view code" on any function to read its source inline, embedded in the page — nothing is fetched.

The page is fully self-contained and offline — no CDN, no telemetry, the graph data is embedded inline. --out produces a single file you can commit or share. Analysis is read-only and never creates a checkpoint.

graph analyzes TypeScript/JavaScript (.ts/.tsx/.js/.jsx/.mjs/.cjs) and Java (.java). TS/JS calls resolve through the TypeScript compiler; Java is parsed with java-parser and resolved through a symbol table (fields, locals, parameters, and the superclass chain) so this.m(), obj.m(), Type.staticM(), inherited methods, and new X() all map to the right declaration. A repo with both languages renders as one combined graph; support for more languages is planned. In a project with no analyzable sources it says so cleanly — the other commands (save/restore/ship) work in any repository regardless of language.

Using it with AI agents

checkpointer is just a CLI, so any agent that can run shell commands can use it. Agents identify themselves with environment variables so their checkpoints are attributed:

export CHECKPOINTER_AGENT=claude-code
export CHECKPOINTER_SESSION="<session-id>"
export CHECKPOINTER_AUTHOR="<name>"   # optional: override the attributed author

Then a checkpointer save records the agent and session automatically.

Claude Code

Install the bundled skill once and Claude Code will know when and how to checkpoint:

checkpointer skill install

This copies a skill into ~/.claude/skills/checkpointer. Claude will then save checkpoints before risky changes, roll back on failure, and offer to ship when you're done.

Cursor and other agents

Point the agent at the command reference above, or copy the skill's guidance into your agent rules (checkpointer skill path prints the bundled skill directory; read SKILL.md inside it). The same env-var protocol applies.

How it works

For each project, checkpointer keeps a bare git repo at ~/.checkpointer/projects/<id>/repo.git. Every checkpoint is a commit there, made with git --git-dir=<shadow> --work-tree=<project> so your project's .git is never read or written. ship transfers the chosen checkpoint's objects into your real repo and builds one ordinary commit from its tree — without resetting your working tree, so your uncommitted work is untouched. It never pushes.

Set CHECKPOINTER_HOME to store checkpoints somewhere other than ~/.checkpointer.

License

Apache-2.0