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

claude-memory-tool

v0.2.1

Published

Sync a project's Claude Code memory and session history across machines via a private git repo, without committing anything to the project.

Readme

claude-memory-tool

Move between machines without Claude Code losing the thread.

Claude Code keeps a project's memory and conversation transcripts in ~/.claude/projects/<path-slug>/, outside the repo. A git clone on a second machine brings the code and nothing else, so you start cold. This tool carries memory and session history across, through a second private git repo you own — so machine B picks up exactly where machine A stopped, --resume included.

Your project repo is never touched. Not one file, not one line in .gitignore. Teammates cloning the project see no trace of any of this.

Install

npx claude-memory-tool install

Drops the skill into .claude/skills/memory-sync/ and four commands into .claude/commands/.

Use

First machine

/memory-setup

It reads your project's origin, asks for a separate private repo to store memory in, and mints a 64-hex id. It then prints three values:

  storage repo:  [email protected]:you/claude-memories.git
  project repo:  [email protected]:acme/checkout-api.git
  project id:    7a265062958de42191e053264405d1c60bac2d588ae6961b4856c4b9eedabea8

Save them. Nothing about this link is committed anywhere, so a second machine cannot discover them — you type them in there. They also live in claude-memory-tool/setup.md on this machine, which is local and gitignored.

Then, before you switch machines:

/memory-sync-upload

Other machines

Clone the project, install, and join:

/setup-second-memory

It asks for the three values, checks the id actually exists in the storage repo, and shows you what is behind it before saving anything:

  ✓ Found "checkout-api"
    last upload:  a3f91c04 by DESKTOP-OFFICE at 2026-08-20T09:12:44Z
    contents:     14 memory file(s), 3 session(s)

That summary is your confirmation the id was right. Then:

/memory-sync-download

Start Claude Code in that directory and --resume. The conversation from the first machine is there.

How it fits together

Machine A                      Storage repo (private)          Machine B
─────────                      ──────────────────────          ─────────
/memory-setup
  → mints id, saves it locally, commits nothing
/memory-sync-upload ─────────► <64-hex>/                            │
                                 manifest.json                      │
                                 sync-log.md                        │
                                 memory/                            │
                                 sessions/                          │
                                                     git clone the project
                                                       (no trace of the tool)
                                                     npx claude-memory-tool install
                                                     /setup-second-memory
                                                       ← you type the 3 values
                               ◄──────────────────── /memory-sync-download
                                                     claude --resume

Two repos, and they never mix:

  • Project repo — your code. Carries nothing belonging to this tool.
  • Storage repo — private, one per user, holds memory and transcripts for every project under one opaque <64-hex>/ folder each. The folder name reveals nothing about the project.

Read this before you set it up

Transcripts contain everything. Every prompt, every file excerpt Claude read, every command's output — including any secret that ever crossed the terminal. Setup refuses a public storage repo, and that refusal is the point, not a formality.

Tracking who has what

Every upload gets a short random ref like a3f91c04. It travels through the manifest, the storage repo's commit message, and both logs — so "which upload does this machine have?" has one exact answer instead of being inferred from clocks that machines disagree about.

Shared log<project_id>/sync-log.md in the storage repo. Uploads only:

| ref | uploaded (UTC) | machine | memory | sessions | had |
|---|---|---|---|---|---|
| `a3f91c04` | 2026-08-20 09:12Z | MACBOOK | 15 | 3 | `7b2e0f11` |
| `7b2e0f11` | 2026-08-19 17:40Z | DESKTOP-OFFICE | 14 | 3 | — |

The had column is what that machine had downloaded when it uploaded — so download history shows up here too, without downloads ever having to write.

Downloads are deliberately not recorded here. Writing on download would turn a read into a push, which fails when two machines pull at once, and would add a commit every time you pull.

Local logclaude-memory-tool/machine-log.md, one per machine, never pushed. Both actions, with the details that only matter to you:

| when (UTC) | action | ref | detail |
|---|---|---|---|
| 2026-08-20 09:12Z | upload | `a3f91c04` | 15 memory files, 3 transcript(s) |
| 2026-08-20 08:55Z | download | `7b2e0f11` | 14 memory files, 3 transcript(s) from DESKTOP-OFFICE; backup at slug.backup-20260820-085502 |

Because refs are exact, upload can tell you precisely where you stand:

✗ This machine is 2 upload(s) behind the storage repo.

  you have:      7b2e0f11
  landed since:  a3f91c04, 55d10e83
  most recent:   MACBOOK at 2026-08-20T09:12:44Z

Design notes

Nothing is committed to the project repo. claude-memory-tool/ contains a .gitignore holding just *, so the directory ignores its own contents including that file. No entry in the project's committed .gitignore, nothing to explain to teammates, and the storage repo URL and project id never leave your machine. The cost is that a second machine cannot discover the link — hence /setup-second-memory.

Paths are rewritten, and they have to be. The state directory is named after the project's absolute path, so it differs per machine, and every transcript line embeds a cwd. Stored transcripts hold a portable __CLAUDE_MEMORY_SYNC_ROOT__ placeholder instead; upload folds the local root into it, download expands it to whatever the local root is. Any number of machines with different paths agree on the stored bytes, which also keeps git diffs free of path churn.

Only the top-level cwd field is touched. Absolute paths inside historical tool results are left alone — they are a record of what happened on another machine, and blind find-and-replace over captured text corrupts more than it fixes.

Download always backs up first, to ~/.claude/projects/<slug>.backup-<timestamp>/.

Upload refuses to clobber a newer upload from another machine. Download first, or pass --force if you are certain this machine holds the state to keep. A machine is never told it is behind its own upload.

Sessions merge by length, not by timestamp. Transcripts are append-only, so "did this machine carry the session further?" is a prefix test. If two machines extended the same session differently, both copies are kept (<uuid>.conflict-<machine>.jsonl) and you are told.

Transcripts older than max_session_age_days (default 30) are not uploaded, and the command says which ones it skipped. Memory files are always uploaded in full.

Line endings are pinned (core.autocrlf=false, plus * -text in the storage repo). Transcripts are compared byte-for-byte, so a Windows checkout rewriting LF to CRLF would turn every cross-platform comparison into a false conflict.

Transport

Plain git against a cached clone under ~/.claude/mem-sync/, using whatever credentials the machine already has — SSH key, credential helper, gh/glab login. No tokens are stored anywhere. GitHub, GitLab, and self-hosted GitLab all take the same code path.

Files on your machine

<project>/
  .claude/skills/memory-sync/     the skill
  .claude/commands/               the four commands
  claude-memory-tool/             all gitignored, by a .gitignore of "*"
    setup.md                      config: the two repos, the id
    state.local.json              what this machine last uploaded/downloaded
    machine-log.md                this machine's readable history

Commands and flags

| | | |---|---| | /memory-setup | --storage-repo <url> --max-session-age-days <n> --force --allow-public | | /setup-second-memory | --storage-repo <url> --project-repo <url> --project-id <64 hex> --force --allow-public | | /memory-sync-upload | --force | | /memory-sync-download | --dry-run |

CMS_MACHINE_NAME overrides the hostname used to attribute uploads, which is useful when several checkouts share one host.

Tests

npm test

Simulates two machines with different home directories and different project paths against local bare repos, and exercises the whole cycle: setup refusals, that the project repo stays untouched, joining by id (including malformed ids, wrong ids, and wrong project repos), cross-machine download with path rewriting, both logs, the ref-based divergence guard, session forks, the age cutoff, and --force.

License

MIT