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

@tricknowtech/context

v0.7.0

Published

Carry a project's LLM context between machines — Claude Code, Codex, Cursor, Copilot, Gemini, Windsurf, Cline, Aider. Local-first, commit it to your repo.

Readme

@tricknowtech/context

Carry a project's LLM context — memory, skills, instructions, and where you left off — between machines.

Local-first: the store is a plain directory you commit to your repo, so context travels with the code. No account, no server, works offline. A hosted Tricknowtech remote is optional and comes later.

npx @tricknowtech/context init

The problem

Open the same project on a second machine and your assistant knows nothing. Instruction files travel with the repo, but the parts that actually accumulate — per-project memory, custom skills and prompts, and the thread of what you were doing — live in your home directory and never leave the machine that built them.

Works with the tool you actually use

Assistants are detected automatically, from what's installed and what the repo already contains:

| Tool | Project files | User-global | |---|---|---| | Claude Code | CLAUDE.md, .claude/** | memory, skills, agents, plans | | OpenAI Codex | AGENTS.md, .codex/** | AGENTS.md, config.toml, prompts | | Cursor | .cursorrules, .cursor/rules/** | global rules | | GitHub Copilot | .github/copilot-instructions.md, instructions, prompts | — | | Gemini CLI | GEMINI.md, .gemini/** | GEMINI.md, settings, commands | | Windsurf | .windsurfrules, .windsurf/** | — | | Cline | .clinerules | — | | Aider | CONVENTIONS.md, .aider.conf.yml | — | | Continue | .continue/** | — |

Each tool's home-directory config is namespaced in the store (assistants/codex/…) and restored to the right place on the other machine — ~/.codex, ~/.gemini, ~/.claude — even when that machine's home and project paths are completely different.

This also works across a team on different tools: a Cursor user's rules sync for a Claude user, because detection keys off what's in the repo, not just what's installed locally. Pin it explicitly if you'd rather:

{ "assistants": ["claude", "codex"] }

What it does

ctx init creates .contextsync/ and installs a /context slash command. From then on:

ctx push      # collect context into the store
ctx pull      # restore it, and print where you left off
ctx status    # what changed since the last push
ctx handoff   # show or write the session handoff
ctx doctor    # check the setup is actually wired correctly

Search everything you've synced (file-based RAG, no database)

Carrying 300 MB of context is only useful if you can find things in it.

ctx index                       # build the index + knowledge graph
ctx search "why does nginx 502 after a deploy"
ctx ask "what did we decide about transcripts"   # context pack for a model
ctx graph startServer                            # what touches this symbol
 18.59  assistants/claude/memory/nginx_upstream_ip_cache.md  [core]
        Recreating the `app` container without also restarting `nginx` causes a
        live 502 outage — nginx caches app's old IP and never re-resolves…

No database, no embeddings, no dependencies. Retrieval is BM25 over an inverted index stored as plain files. The postings are sharded by term hash, so a four-word query reads four small files instead of parsing one huge one — the access pattern a key-value store would give you, using only the filesystem. Scoring needs nothing but term frequencies and document lengths, so it is deterministic, offline, and reproducible.

The tradeoff versus embeddings is honest: there's no synonym matching, so "auth" won't find "login" unless the word appears. In exchange you get zero install weight, no model download, no network call per query, and results you can explain. On technical corpora the rare exact terms — identifiers, file names, error strings — are what you actually search for, and those are exactly what BM25's IDF rewards.

The graph half

ctx index also builds a knowledge graph by extracting definitions and imports across TypeScript, Python, Go, Rust, PHP, Java and others, then linking your context documents to the code they mention.

That closes a gap pure keyword search can't: a memory note explaining why something breaks often never contains the word you searched for. Documents one hop from a matched symbol are pulled in, discounted so they can never outrank a direct textual match.

It uses graphify's exact schema — same node/edge fields, same relation vocabulary. If graphify-out/graph.json exists it is merged in and wins, since it was built with an LLM and carries semantic relations regex extraction cannot infer. Think of this as the AST-only equivalent: cheaper, offline, instant.

Transcripts are opt-in

ctx index --transcripts

They're ~99% of the corpus by volume. Indexing them by default turned a 5-second command into 4 minutes and produced an index larger than the data itself, so you ask for them explicitly.

Cut what a session costs in tokens

The expensive part of an LLM session is rarely the conversation — it's the context re-sent on every request. ctx budget prices it:

  per turn         4.9k tokens  × 100 turns = 492.7k
  per session      8.9k tokens  × 1        = 8.9k
  on demand       28.8k tokens  (only when pulled in)

  session total ≈ 501.6k tokens before any code or conversation

Biggest lever:
  CLAUDE.md is 4.8k tokens on *every* request.
  Halving it saves ~237.5k tokens over 100 turns.

That split is the whole point. An 18k-token skill loaded on demand is cheap; a 4.8k-token instruction file is not, because you pay it every turn. It also flags content duplicated across files, which you pay for twice.

Then load only what a task needs, instead of everything:

ctx pack "fixing an nginx 502 after redeploying containers"
## assistants/claude/memory/nginx_upstream_ip_cache.md
nginx's `fastcgi_pass app:9000` resolves the hostname once and caches it…
---
Pack ≈ 590 tokens vs ≈ 42.6k for all context — 99% smaller.

The practical recipe: move situational detail out of instruction files into memory or skills, then retrieve it on demand. Instruction files should hold what's true every turn; everything else is better paid for only when it's relevant.

Token counts are estimates (±15%) — enough to decide what to cut, not a billing oracle.

Continue a session on a VPS

Move the whole context — including the current session's transcripts — to a server, so you can ssh in and carry on exactly where you stopped:

ctx remote add vps [email protected]:/srv/myproject
ctx push --to vps --restore

--restore is what makes it a continuation rather than a file copy: it runs the restore on the far end, so memory, skills, plans and transcripts land where the assistant actually reads them. Then just:

ssh [email protected]
cd /srv/myproject && claude --resume

Bring work back the other way with ctx pull --from vps.

Transport is your own ssh and rsync, so ~/.ssh/config aliases, jump hosts, agent forwarding and custom ports all work untouched. rsync means the second push only sends what changed. Without rsync it falls back to streaming a tar over ssh, which always sends everything.

Measured on a 327 MB context: 92 MB transferred, ~48s, and the restored transcript was a byte-exact prefix of the live local one.

Start with ctx doctor if anything seems off — it verifies the pieces that fail silently, including whether your store is accidentally gitignored (in which case it never reaches the other machine) and whether restored memory lands where Claude Code actually reads it.

Commit .contextsync/ and your teammates — and your other laptop — get the same context on clone.

It skips what git already carries

Your CLAUDE.md is already in the repo, so copying it into the store would just create a second copy that drifts. The collector checks git ls-files and leaves tracked files alone. What it does capture is the part that never travels:

| Store path | Comes from | |---|---| | memory/ | ~/.claude/projects/<project-key>/memory/ | | skills/ | ~/.claude/skills/ | | agents/ | ~/.claude/agents/ | | user/ | ~/.claude/CLAUDE.md, settings.json | | project/ | untracked instruction files in the repo | | artifacts/ | derived indexes, opt-in (--artifacts) | | handoff.json | written by /context push |

Paths are rewritten on restore

Claude Code names its per-project directories after the absolute project path — /root/my-app becomes -root-my-app. Clone the repo somewhere else and that key is wrong. The manifest stores paths as templates ({userClaude}/projects/{cwdKey}/memory/…) and ctx pull recomputes them for wherever the repo actually lives.

The handoff

/context push asks the model to write .contextsync/handoff.json first — goal, decisions made, open threads, files touched, next step. Only the model has the conversation; only the CLI has the disk, so the slash command is the one place both are available.

On the other machine, /context pull restores everything and reads the handoff back, so the new session starts oriented instead of blank:

Where you left off  (2h ago)

  Goal       Build the context-sync tool and publish it
  Next step  Start the cloud remote, leading with the token-scoping fix

  Decided:
    · Local-first: store is committed to the repo, cloud is an optional remote
  Still open:
    · mcp:* token abilities are granted but never checked

The handoff is validated on write and on read — a model-authored file that's malformed is reported rather than silently ignored, since a handoff that looks present but says nothing is worse than an obviously absent one. ctx push tells you when no handoff was written, so you never discover it only after arriving on the other machine.

Safety

The store gets committed, and a committed credential is permanent — so ctx push scans everything first and refuses if it finds anything that looks like a secret:

Refusing to push — 2 possible secrets found:

  user/settings.json:14  [assigned-secret]  wJal********MPLEK
  memory/deploy.md:8     [aws-access-key-id]  AKIA********MPLE

These would be committed to the repository and be very hard to remove.

.env files, ~/.claude/.credentials.json, .claude.json, and private keys are never collected at all, at any tier.

Session transcripts are excluded from local mode entirely. They run to hundreds of megabytes, are append-only, and carry the largest leak surface (full tool output). They will be supported through the hosted remote, where content-addressed chunking makes them practical.

Options

| Flag | Effect | |---|---| | --artifacts | include derived indexes (graphify-out/, etc.) | | --dry-run | show what would sync, write nothing | | --force | init: overwrite config · pull: overwrite differing files | | --allow-secrets | push despite scan hits — think first |

ctx pull never overwrites a local file whose contents differ; it lists them and leaves them alone until you pass --force.

Configuration

.contextsync/config.json:

{
  "projectId": "…",
  "name": "my-app",
  "rootHint": "/root/my-app",
  "tiers": ["core", "handoff"],
  "artifactPaths": ["graphify-out"],
  "exclude": ["**/*.log"],
  "remotes": {}
}

Programmatic use

import { collect, findProjectRoot, loadConfig, LocalStore } from '@tricknowtech/context'

const root = findProjectRoot()!
const cfg = loadConfig(root)!
const { files, skippedTracked } = collect(root, cfg, ['core'])
new LocalStore(root).write(files, root)

License

ISC © Tricknowtech