One memory for every AI agent on your machine: tell one, and the rest know.
A gate, not a store — it decides what gets in, and writes down why.
Nothing in it expires, and nothing is ever removed behind your back.
Node 22.5 or newer, and nothing else:
npm install -g nosyparker
nosyparker setup
To know it worked, open one of your agents and ask it something only your shared memory would know.
The file is yours, wherever it is. No account, nothing to sign up for, nothing hosted, no network requests and no telemetry: the only server here is the small one your agents start on your own machine to read that file, and nothing it holds ever leaves it.
Every agent on your machine reads and writes the same file. The agent decides what is worth keeping: it is told, when it connects, to store what it learns about you that will still be true next week, and to say so when it does. Ten things an agent can do:
- remember a fact about you, replacing an older one if you have changed your mind.
- recall what it already knows, before it asks you something twice. A search that runs for more than ten seconds is stopped and told to narrow, rather than answered with part of a result.
- list everything currently known about you.
- forget something, with a reason. This puts it away rather than deleting it: it stops being shown and stays in the file.
- restore something that was forgotten or replaced, so it is shown again.
- why — the record of every offer ever made and what became of it, including the ones that were refused and why.
- review_start — begin reading back through what is stored, with the date each thing was stored on.
- review_finding — record what it concluded about one memory, and why.
- review_end — finish, after which that review takes nothing more.
- review_undo — put back everything one review changed, all at once.
Refusing is half of it, and a refusal is an answer rather than an error. Anything shaped like a password, a key or a card number is not stored, and is not written into the record either — offering one leaves the fact and never the text. Empty text is refused, so is something you have already said word for word, and so is a file: paste an agent a log and it is told to keep the fact and leave the file. Every one is written down with the rule that decided it.
Digits are read as digits, not only ASCII ones: ۴۱۱۱ ۱۱۱۱ ۱۱۱۱ ۱۱۱۱ is the same card as 4111 1111 1111 1111 and both are refused. That is verified for Persian, Arabic-Indic, Devanagari, Bengali, Tamil, Thai and full-width. It is a screen rather than a guarantee — it catches the careless case, which is the one that happens.
This keeps facts, and a file that every agent on your machine can read is the wrong place for a password. So the refusal is not a gap to work around: keep the secret in a password manager, and keep here the sentence that says where it is.
That sentence is the part people do not think to write down, so here is one:
The code for the clinic's results portal is in my password manager, saved under "Meridian Health", and the login is the email ending 4412.
An agent that reads that knows where to look and what to ask for, which is everything it needs and none of the secret. Any password manager with a command line will do; nosyparker does not integrate with one and does not need to.
One limit, which is real and which nothing changes: at the moment an agent fetches a secret and reads it out to you, that secret is in the conversation. Keeping it in a vault decides where it rests, not what happens when it is used.
The last four are for tidying up. "Next week I am presenting at the all-hands" was worth remembering the day you said it and means nothing a year later, and an agent can read back through what is stored and say so.
What it cannot do matters more:
- Nothing here decides anything from a date. No code in this project looks at when something was stored and concludes it should go. Every memory carries the date, the agent is shown it, and the agent works out — by reading the sentence — whether the moment it named has gone by. "I live in Tehran" names no moment, and is as true after ten years as the day you said it.
- A review cannot forget and cannot delete. Forgetting is you saying you do not want something shown. All a review can do is mark something no longer current, or link it to a newer memory that replaced it. Both are reversible.
- "I could not tell" is a real answer. If two memories disagree and nothing says which came first, the agent says so and changes nothing. Its reasoning is recorded either way, so you can judge afterwards whether it thought well.
Nothing runs a review on a schedule. What the store does instead is say, at the end of every answer it gives an agent, when one is overdue — twenty memories since the last review, or a week — and which agent is already doing one, so the others stand down. That line is counting the store's own record of what it did and when; it never reads a memory's date.
A review can put away a large part of a store in one pass, and nothing will
mention it unless the agent does or you run doctor. nosyparker undo-review <number>
puts a whole review back; the number is in why, and anything you changed
yourself since is left alone.
nosyparker export memories.json
Every memory in every state, every review, and the whole record of what was decided and why — not only what is currently shown. Plain JSON, which any program opens and you can read. It will not write over a file already there.
Nothing here deletes a memory. If you want one gone for good, that is a command you run yourself, and it cannot be undone:
node "$(npm root -g)/nosyparker/scripts/purge.mjs" --id 4 --yes
Install it globally rather than through npx: setup writes the path it is
running from into every config it touches, and refuses to run from an npx
cache, where that path rots.
It looks for twenty-two clients, writes its entry into the ones it finds, and sorts them into three groups — the ones that answered us, the ones you should check yourself, and the ones that did not work, with the reason. CLIENTS.md lists all of them and says which group each is in.
It only ever adds or removes its own entry, and where it edits a config file it
keeps a copy in ~/.nosyparker/backups/ first, never replaced.
Linux is the only platform any of this has been watched on. The macOS and
Windows locations are the standard ones those builds use and have not been
seen working here, so on those two uninstall looks for a file it has never
been shown, finds nothing, and says nothing either way.
The last thing it prints is which applications to close and reopen. All but one of them read their config only at startup; Hermes watches its file and reloads by itself, and setup says so.
If it does not know your client, nosyparker setup --print-config prints the exact thing
to paste, and naming one it does know (nosyparker setup --print-config zed) prints that
client's shape, path and pitfalls. CONNECTING.md has the
by-hand version.
If something is not working:
nosyparker doctor
It says which clients are working, which cannot be asked, and for anything
broken what is wrong and what to do — plus whether your store opens, whether a
review was left open, and what the recent reviews did. The commonest answer is a
changed Node version, and running nosyparker setup again fixes it. It changes
nothing.
You do not have to remember to run it for that one. Setup writes down which
Node, and which copy of nosyparker, each entry was written with, and the next
time you run any command that opens the store on a machine where that path has
gone, it says so in one line on stderr and names setup and doctor.
If that does not resolve it, the issues page is the place to say so.
nosyparker uninstall
Takes its entry out of every client that has one, including the one Cursor's own
command writes, and changes nothing else in those files. Running it twice is not
an error. nosyparker uninstall kiro does the same for one client and leaves
the rest alone; the names are the ids in CLIENTS.md.
One thing it does delete, and it belongs here rather than in the engineering notes: a configuration file that existed only because setup created it, and that is empty once our entry is gone, is removed — along with any directories that had to be made to hold it. A file that was already on the machine is never deleted, and neither is one with anything else left in it. The test is on the contents, not on our say-so.
That removes the wiring, not the memories. Everything nosyparker keeps is in one folder:
~/.nosyparker/memory.sqlite your memories
~/.nosyparker/actions.log what it did to which file and when, never contents
~/.nosyparker/backups/ a copy of each config as it was before it was edited
Delete the folder and all of it is gone. NOSYPARKER_STORE moves the memories
elsewhere; the other two stay here.
One thing to know about that last folder: the copies in it are other programs' configuration files exactly as they were, and some of those files are allowed to hold API keys. The copies are written readable by you alone — mode 0600 on Linux and macOS; on Windows, whatever your user folder allows — and are never read back by anything here; they exist so that an edit can be undone. If you would rather not keep them, they are yours to delete.
Searching for a number finds it in any script. search 2026 and
search ۲۰۲۶ return the same memories, and so do search 10 and search ۱۰.
Until 0.0.5 that was only true of short terms: the search index was built on the
text exactly as written, so a longer number written in Persian and the same
number written in ASCII were two different things to it. There is now a second
index over the folded text, and search reads that one.
It is built the first time this version opens your store — 13 milliseconds on a store of two hundred memories, under a second on one of a hundred thousand — and it adds about a quarter to the file's size. Nothing to run, and it does not change the schema version, so a store this version has opened still opens under 0.0.4.
Upgrading from 0.0.3 or earlier. This version reads digits as digits in any script, which changes how memories are indexed — so a store written before it needs its index rebuilt once. Close your editors and assistants, then:
node "$(npm root -g)/nosyparker/scripts/migrate.mjs" --yes
It copies your store, rebuilds the copy, checks the copy against the original
seven ways — including that every search which found something before still
finds it — and only then puts the copy in place. Your store as it was is kept
beside it as a backup. Nothing deletes that backup; you do, when you are
satisfied. If you skip this, memories written earlier stay findable exactly as
they are today; what you would miss is ۱۰ and 10 counting as the same
number.
If something has your store open it now says so and stops before copying
anything, rather than doing the whole migration and failing at the last step.
And if a .migrating file is left behind, it tells you which of the two
situations you are in: a run that changed nothing, which you can move aside and
retry, or one it cannot account for, which it will not touch.