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

synaptly

v0.1.8

Published

Your AI's memory, synced. A private home for what Claude Code, Codex or ChatGPT learned about you and your projects.

Readme

syn

Your AI's memory, synced.

Install

npm install -g synaptly

Use

syn login [--name <device>]        Sign this machine in
syn init [<mind>]                  Link this folder to a mind
  --mind <name>                    The same name, as a flag
syn snap [-m <message>]            Send what changed here, bring what changed there
  --retry-conflicts                Resend conflicts (resolve them elsewhere first)
  --quiet                          Only errors and the final conflict lines
syn journal "<text>"               Append one line to today's journal
  --tool <name>                    Label the entry with the tool that wrote it
syn conflicts                      Show both sides of every conflict
  --brief                          One line naming them, or nothing when clean
syn resolve <path> --mine          Close a conflict, keeping the version that conflicted
  --theirs | --both | --from <f>   ...or the server's, or both, or a merge of yours
  --id <version>                   Pick one conflict when a path has several
syn status                         See what would change, without changing it
  --retry-conflicts                The same view snap would act on
syn hook install                   Sync when a Claude Code session starts here
syn hook status                    Say whether this folder has the hook
syn watch [--every <n>]            Keep this folder in sync
  --every instant|5m|15m|30m|manual
  --once                           One pass, then exit

Unknown options are refused, not ignored: syn snap --retry-conflict stops and says so rather than reporting success without retrying anything.

syn status never writes anything: it reads the same three pictures syn snap does and prints what syn snap would do.

Exit codes

| Code | Meaning | |---|---| | 0 | The pass went fine. Conflicts, if any, are named in the output. | | 2 | syn refused something the server sent, or a file it cannot upload: a path that leaves the project folder, or a file type the server does not accept. | | 1 | Could not run at all: not signed in, folder not linked, unreadable settings, server unreachable. |

Non-zero means this pass had a problem, not that there is work to do. A waiting conflict is not a failure, so it does not change the code — syn snap and syn status both say so in their output instead.

Environment

| Variable | What it does | |---|---| | SYN_API | Which API syn login signs in to. Default https://api.synaptly.dev. It does not redirect the other commands: once you are signed in the host comes from your saved credentials, and for a linked folder from its .syn.json. | | SYN_HOME | Where credentials and links live. Default ~/.syn. |

What gets synced

MEMORY.md, memory/, assets/ and refs/. The journal/ folder is written by the server: it comes down, it never goes up.[^journal]

[^journal]: The CLI side of journal/ is built and tested — it downloads those entries and will never propose deleting them. They will not appear until the server lists them in the manifest, which it does not do yet.

Linked folders

If a folder or file inside MEMORY.md, memory/, assets/ or refs/ is a symlink or junction that points outside the project, syn refuses it — in both directions and from the very first run. It names the path and says why:

⚠ memory/notes.md  Refusing "memory/notes.md": it resolves outside the project folder through a symlink. Nothing under it syncs, in either direction.

So pointing memory/ at your real notes folder somewhere else on disk will not work. Do one of these instead:

  • keep the real files inside memory/, or
  • link the whole project folder rather than a folder inside it — run syn init where the files actually live.

This is a deliberate limit, not an oversight. syn cannot tell a link you made on purpose from one that arrived in a git clone, and writing through either lands a downloaded file outside the folder you pointed it at. So a link it will not write to is one it will not read from either. The alternative is worse: a rule that changes under you, uploading a folder happily until the day the server first hears about it and then going quiet.

Conflicts

If two machines change different parts of the same file, the server merges them and syn snap brings the result down. If they change the same lines, your version is kept beside the good one as a dendrite and syn snap tells you. Nothing is ever lost and no conflict markers are written into your files.

A file with an open conflict is not sent again until something changes on one side or the other. --retry-conflicts sends it anyway.

Claude Code

syn hook install writes a SessionStart hook into the project's .claude/settings.json — never your global settings — merging with whatever is already there, and installing twice adds nothing. Every Claude Code session in that folder then starts with syn hook run: a quiet sync, plus one line naming any open conflicts, so the agent finds out on its own. A sync that worked but found conflicts exits 0 on purpose: in Claude Code hooks a 2 blocks the action, and a waiting conflict is a state, not a failure.

If CLAUDE.md or AGENTS.md already exist in the folder, install also leaves them a replaceable block between <!-- synaptly:start --> and <!-- synaptly:end -->: read MEMORY.md at the start, note what happened with syn journal, and show both sides of any conflict before doing anything else.

A journal entry is one line about what happened, up to 8 KB. Anything longer belongs in a memory file, not the journal — the server enforces the same cap.

Files it keeps

  • ~/.syn/credentials.json — your device token. Treat it like a password.
  • ~/.syn/links.json — which folders are linked to which minds.
  • .syn.json — the mind this folder belongs to. Safe to commit.
  • .syn/state.json — what the last sync saw. Do not commit it.
  • .syn/trash/ — files deleted on another device. Nothing is deleted outright.

syn writes .syn/.gitignore for you, so git ignores that folder on its own.