{
  "markdown": "<h1 align=\"center\">sthayi</h1>\n\n<p align=\"center\"><strong>AI memory you own.</strong></p>\n\n<p align=\"center\">\n  A sovereign, local-first memory / skills / MCP-registry plane — so supported AI clients on your\n  machine can read and write <em>one shared local</em> memory that <em>you</em> own.\n</p>\n\n---\n\n> **sthayi** (Sanskrit): *permanent, enduring*. The *sthāyī bhāva* is the enduring emotion\n> beneath transient states; the *sthāyī* in Hindustani music is the refrain a raga always\n> returns to. Pronounced **\"STAY-ee.\"**\n\nYour memory today can be scattered across Claude, ChatGPT, Gemini, Cursor, and CLI agents —\nmultiple apps, multiple fragments, none of them yours. Sthayi is not another silo and not a\nreplacement: it coexists with each app's built-in memory — *in addition, not instead* — as one\nshared local memory exposed to supported clients over\n[MCP](https://modelcontextprotocol.io). There is no hosted Sthayi service and no Sthayi account —\nonly the local MCP server running on your machine. Theirs stay theirs. This one is yours.\n\n## Quickstart\n\n### Prerequisite: Node.js 22 or 24\n\nSthayi v0.1.3 supports Node.js 22 and 24, with Node 24 LTS recommended, and requires npm. Check\nboth before installing:\n\n```text\nnode --version\nnpm --version\n```\n\n`node --version` must begin with `v22.` or `v24.`. If Node is missing or reports any other major\nversion—including Node 25—install Node 24 LTS from the\n[official Node.js download page](https://nodejs.org/en/download) using the normal/default location\noffered for your operating system. npm is included with the standard Node.js distribution. Reopen\nyour terminal afterward, then run both checks again. Sthayi refuses an unsupported Node major\nbefore loading its native SQLite dependency and explains this repair.\n\nNode.js does not need to be installed inside Sthayi's prefix. Installing Node.js is a separate\nprerequisite and may require administrator approval, depending on the operating system and install\nmethod. Once Node.js and npm are available, the Sthayi installation below stays in user space and\nneeds neither `sudo` nor administrator rights.\n\n### Install and initialize\n\n> Sthayi v0 uses a `better-sqlite3`-backed local store. The user-space command below first refuses\n> any Node major other than 22 or 24, then requests the npm `latest` tag explicitly and makes npm\n> enforce the package's engine declaration. Those two npm qualifiers prevent an unsupported Node\n> runtime from silently selecting an older compatible release. Do not substitute `npx sthayi init`.\n\nContributing from a source checkout instead? Use the [Development](#development) workflow.\n\n```bash\n# macOS / Linux — bash or zsh\nnode -e \"const m=Number(process.versions.node.split('.')[0]);if(m===22||m===24){}else{console.error('Sthayi requires Node.js 22 or 24 (24 LTS recommended). Detected '+process.version+'. Install Node.js 24 LTS: https://nodejs.org/en/download');process.exit(1)}\" && npm install -g --prefix \"$HOME/.local\" --engine-strict sthayi@latest && \"$HOME/.local/bin/sthayi\" init\n```\n\nOne line: install once somewhere durable, then detect your AI clients and wire them in one\nkeystroke.\n\nAfter the wizard completes, verify the default installation and state directory:\n\n```bash\n\"$HOME/.local/bin/sthayi\" doctor\n```\n\nThis invokes the package from the durable install prefix; `doctor` reports the configured state\ndirectory, including a custom absolute `STHAYI_HOME` when one is set.\n\n**Why the npm flags, and what they do not touch.** `--prefix` and `--engine-strict` are\n**per-invocation flags**: they tell this one `npm install` where to put the package and to refuse an\nunsupported engine, while changing **nothing** in your npm\nconfiguration. No `~/.npmrc` is written, `npm config get prefix` reads exactly what it read before,\nand every other npm command you run is unaffected. The install lands under your home directory, so\ninstalling **Sthayi itself** needs no admin rights once Node.js and npm are available — including on\nmachines where npm's default global prefix is root-owned and a plain `npm install -g sthayi` fails\nwith `EACCES`.\n\nWhere things land:\n\n| Path | What |\n|---|---|\n| `~/.local/lib/node_modules/sthayi` | the package itself — the durable install the launcher pins |\n| `~/.local/bin/sthayi` | npm's shim, a relative symlink into the line above |\n| `~/.sthayi/` | **your memory** — `sthayi.db`, the vault `key`, `journal.checkpoint`, `skills/`, `bin/` |\n\nThe package and the memory are **two separate directories**, and they are removed by two separate\nacts: `npm uninstall` takes the first, and the second is yours alone (see\n[Upgrade & uninstall](#upgrade--uninstall)).\n\nNo account. No required API key for ordinary core operation. No telemetry. No administrator rights\nfor the Sthayi user-space install once Node.js and npm are available. Wiring, however, edits each\nAI client's own config file (after saving a `*.sthayi-bak-*` backup beside it) — so removing Sthayi\nstarts with `sthayi unwire`, which restores or surgically updates those configs as described below.\nRemoval of the state directory itself is a separate decision, and one Sthayi leaves to you; see\n“Upgrade & uninstall” below.\n\n**`npx sthayi init` is refused, and this is why.** `npx` runs the CLI out of npm's *download\ncache*, which is pruned without warning. `init` writes launchers that pin the exact CLI they were\nwritten from, so a launcher pinned into that cache is wiring that breaks the next time npm cleans\nup. Sthayi refuses to write one and tells you where to install instead — onboarding is a durable\ninstall first, then `sthayi init`. (Commands that write no launcher — `npx sthayi@latest status`,\n`npx sthayi@latest doctor`, `npx sthayi@latest search` — do run from the cache. `search` is **not**\nread-only, though: every search journals a `memory_retrieve`, bumps recency, and strengthens the\nassociation graph.)\n\n**What “durable” means: anywhere you keep, not anywhere privileged.** Only three locations are\nephemeral — an `_npx`/`_cacache` path, your system temp directory, and your npm cache. *Everything\nelse* is pinned exactly where it stands. **No Sthayi installation route below needs admin rights or\n`sudo` once Node.js and npm are available** — where a route cannot proceed it fails outright, and\nthe answer is a different route, never elevation. Each is one copy-pasteable bash/zsh line that\nruns as typed:\n\n```bash\n# 1. THE HEADLINE ROUTE — a prefix inside your own home. This is the durable user-space route.\nnode -e \"const m=Number(process.versions.node.split('.')[0]);if(m===22||m===24){}else{console.error('Sthayi requires Node.js 22 or 24 (24 LTS recommended). Detected '+process.version+'. Install Node.js 24 LTS: https://nodejs.org/en/download');process.exit(1)}\" && npm install -g --prefix \"$HOME/.local\" --engine-strict sthayi@latest && \"$HOME/.local/bin/sthayi\" init\n\n# 2. npm's default global prefix. Available ONLY when your account can already write that prefix\n#    — version managers normally put it inside your home. A default single-user Homebrew install\n#    normally makes its prefix writable by the installing user. Check: npm config get prefix.\n#    If your account cannot write that prefix, use route 1; never add sudo. Its bin is usually on PATH.\nnode -e \"const m=Number(process.versions.node.split('.')[0]);if(m===22||m===24){}else{console.error('Sthayi requires Node.js 22 or 24 (24 LTS recommended). Detected '+process.version+'. Install Node.js 24 LTS: https://nodejs.org/en/download');process.exit(1)}\" && npm install -g --engine-strict sthayi@latest && sthayi init\n\n# 3. A plain local install is durable too. Its binary lives in node_modules/.bin.\nmkdir ~/sthayi && cd ~/sthayi && node -e \"const m=Number(process.versions.node.split('.')[0]);if(m===22||m===24){}else{console.error('Sthayi requires Node.js 22 or 24 (24 LTS recommended). Detected '+process.version+'. Install Node.js 24 LTS: https://nodejs.org/en/download');process.exit(1)}\" && npm i --engine-strict sthayi@latest && ./node_modules/.bin/sthayi init\n```\n\nRoute 1 is the headline because a normal per-user home is the most reliable writable location.\nRoute 2 is the shorter line, and it is worth using when you know the prefix is writable by your\naccount — but it is **not** universally admin-free.\n\n**PATH is optional, and irrelevant to the MCP integration.** Your AI clients invoke\n`~/.sthayi/bin/sthayi-mcp` **by absolute path**, so wiring works whether or not anything is on your\nPATH. PATH only decides whether you can type `sthayi` in a terminal. `init` also writes\n`~/.sthayi/bin/sthayi`, a launcher pinned to the same install, so the `sthayi <command>` forms\nbelow work by full path (`~/.sthayi/bin/sthayi status`) — or on PATH, once. Both launchers live in\nyour state directory, so where you have set `$STHAYI_HOME` they are `$STHAYI_HOME/bin/…` instead;\n`sthayi doctor` reports the home in use:\n\n```bash\nexport PATH=\"$HOME/.sthayi/bin:$PATH\"    # add this line to your shell profile\n```\n\n**Windows:** the same architecture and the same user-space prefix. The per-shell forms below are\n**host-validated** (evidence recorded at v0.1.0) with the checksum-verified packed tarball under a standard\n(non-administrator) account. That packed-tarball evidence does not itself cover delivery from the\nnpm registry; the npm package-name fetch smoke is a separate pre-announcement release gate.\nSthayi never modifies PATH itself, on any platform.\n\n**Windows security scope.** Sthayi's hardened filesystem discipline — the trust boundary that\nprotects your state directory — is a **POSIX (macOS/Linux) guarantee**. Windows has neither uids\nnor POSIX mode bits, and no `O_NOFOLLOW`, so every part that depends on them is skipped there. On\nWindows there is **no ownership check, no permission-bit policy, no hard-link check, no ancestor\nownership/writability check, and no trust-boundary directory-identity check**: a state directory\ndeleted and recreated at the same pathname is accepted, and Sthayi claims\n**no root-replacement protection on Windows**. What applies on every platform: symlink and\nnon-directory refusals at any depth, one-level-at-a-time creation, exclusive-create temp names,\natomic rename, and descriptor-level re-validation with byte caps. Full statement:\n[`docs/sthayi-v0-spec.md`](docs/sthayi-v0-spec.md) §1.\n\n**Windows commands — one shell per block, never mixed.** The three Windows shells disagree about\nstatement separators and about how an environment variable is spelled, so each block below is\nwritten for exactly one of them. Do not paste a line from one block into another. In particular\nWindows PowerShell 5.1 has no `&&` operator at all. Its separator is `;`, which runs the next\nstatement **unconditionally** — so that block checks the install's **success state (`$?`) and its\nexit code (`$LASTEXITCODE`)**, both, before it runs `init`. Both are needed because they fail in\ndifferent ways: `$LASTEXITCODE` is written only by a native command that actually ran, so an npm\nthat could not be resolved at all never touches it and an exit-code-only gate reads a stale zero\nleft by some earlier command. `$?` reports the immediately preceding statement's success, and it is\ncaptured into `$ok` before anything else can overwrite it. Without both checks a failed install is\nfollowed by an `init` attempt against\nwhatever stands at the shim path, which on a prefix you have installed into before is a shim from\nthat earlier attempt, still pinned at an entry this install never refreshed.\n\n```powershell\n# PowerShell 7\nnode -e \"const m=Number(process.versions.node.split('.')[0]);if(m===22||m===24){}else{console.error('Sthayi requires Node.js 22 or 24 (24 LTS recommended). Detected '+process.version+'. Install Node.js 24 LTS: https://nodejs.org/en/download');process.exit(1)}\" && npm install -g --prefix \"$env:LOCALAPPDATA\\sthayi\" --engine-strict sthayi@latest && & \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" init\n```\n\n```powershell\n# Windows PowerShell 5.1\nnode -e \"const m=Number(process.versions.node.split('.')[0]);if(m===22||m===24){}else{console.error('Sthayi requires Node.js 22 or 24 (24 LTS recommended). Detected '+process.version+'. Install Node.js 24 LTS: https://nodejs.org/en/download');process.exit(1)}\"; $nodeOk = $?; if ($nodeOk -and $LASTEXITCODE -eq 0) { npm install -g --prefix \"$env:LOCALAPPDATA\\sthayi\" --engine-strict sthayi@latest; $installOk = $?; if ($installOk -and $LASTEXITCODE -eq 0) { & \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" init } }\n```\n\n```bat\n:: Windows cmd\nnode -e \"const m=Number(process.versions.node.split('.')[0]);if(m===22||m===24){}else{console.error('Sthayi requires Node.js 22 or 24 (24 LTS recommended). Detected '+process.version+'. Install Node.js 24 LTS: https://nodejs.org/en/download');process.exit(1)}\" && npm install -g --prefix \"%LOCALAPPDATA%\\sthayi\" --engine-strict sthayi@latest && \"%LOCALAPPDATA%\\sthayi\\sthayi.cmd\" init\n```\n\nAfter `init` completes, verify the default state directory with the block for your shell:\n\n```powershell\n# PowerShell 5.1 or 7\n& \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" doctor\n```\n\n```bat\n:: Windows cmd\n\"%LOCALAPPDATA%\\sthayi\\sthayi.cmd\" doctor\n```\n\nThese invoke the package from the durable install prefix; `doctor` reports the configured state\ndirectory, including a custom absolute `STHAYI_HOME` when one is set.\n\n**Windows layout differs from POSIX, by npm's own design.** With `--prefix <dir>` on Windows npm\nputs the command shims **directly in `<dir>\\`** and the package under **`<dir>\\node_modules`** —\nthere is no `lib/node_modules` and no `bin/` level, which is why the invocation above is\n`<dir>\\sthayi.cmd` rather than `<dir>\\bin\\sthayi`. By default, your memory lives at\n`%USERPROFILE%\\.sthayi\\`, with launchers under its `bin\\` directory. If `STHAYI_HOME` is set, the\nstate and launchers live under that absolute directory instead. Invoke Sthayi by full path, or add\nthe applicable `bin\\` directory to your *user* `Path` once (Settings → search “environment\nvariables” → edit `Path` → New) for a persistent `sthayi` command in new terminals.\nThe Windows user-space prefix, layout, shim and init path is **host-validated** (evidence recorded at v0.1.0) on\nWindows 11 Pro 24H2 x64 under Node 22.23.2, using a standard (non-administrator) account and the\nchecksum-verified packed tarball. Windows PowerShell 5.1, PowerShell 7.6.4 and `cmd.exe` all\ncompleted their install-and-init forms; the CLI, native SQLite binding, MCP server and\nreinstall/repin/unwire/uninstall lifecycle also passed. That packed-tarball evidence does not itself\ncover delivery from the npm registry; the npm package-name fetch smoke is a separate\npre-announcement release gate.\n\nThen ask any wired assistant: *\"Use Sthayi memory: what do you know about my current projects?\"* —\nand they all answer from the same memory.\n\n## Memory bill of rights\n\nYour memory is:\n\n- **Portable** — Sthayi uses an open, versioned SQLite schema. A memory pack is a masked context\n  document, not a restorable backup.\n- **Private** — ordinary core operation is local and sends nothing to Sthayi. An explicitly invoked\n  Oracle job sends bounded, masked batches to your chosen provider; a pack leaves the machine only\n  when you deliberately export or share it.\n- **Inspectable** — an append-only, hash-chained journal records every write and retrieval.\n- **Deletable** — your memory is one local state directory (`$STHAYI_HOME` when you set it,\n  `~/.sthayi` otherwise; `sthayi doctor` reports the one in use). Sthayi keeps its state in that\n  local directory and retains no hosted copy, so the end of it is yours alone to decide and needs\n  no permission from anyone. `sthayi unwire` restores client configs (untouched-since-wire configs\n  come back byte-exact; edited ones lose only the Sthayi entry and preserve the other edits).\n  Sthayi does not yet ship a validated erase command, and this page publishes no procedure for\n  erasing a state directory by hand — see [Upgrade & uninstall](#upgrade--uninstall) for why a\n  printed location is not a verified removal target.\n- **Yours** — MIT-licensed, no CLA, no lock-in; run it forever without us.\n\n## Never-paywall list\n\nThese are free and open forever:\n\n- the store · the schema · the MCP server · the importers · the prompt pack\n\n## How it works\n\n```\n AI clients (Claude Desktop/Code, Cursor, Gemini CLI, Codex)\n        │ stdio MCP by default\n        ▼\n  packages/cli  ── wizard / commands / MCP server entry\n        │\n  packages/core ── domain logic (browser-clean: no fs/net/process imports)\n        │ StorageDriver port\n  better-sqlite3 driver  →  ~/.sthayi/sthayi.db (+ key file, config.json, bin/)\n```\n\n`sthayi serve --http` optionally serves the same MCP tools over authenticated loopback HTTP at\n`127.0.0.1`; it is not a hosted or remote Sthayi endpoint. Exposing that listener through a tunnel,\nreverse proxy, Tailscale, or VPS is an explicit user action outside Sthayi.\n\n- **The diary (journal).** Every change is written to an append-only, tamper-evident log — you\n  can always answer \"why does it think that?\"\n- **The safe (vault).** Secrets are detected on write and masked to pseudonyms; detected canonicals\n  remain encrypted locally, while Oracle batches and packs contain their pseudonyms instead.\n- **The front door (MCP).** Supported AI clients connect through one standard plug; wiring is one\n  command. Unwire restores an untouched-since-wire configuration byte-for-byte. If it changed\n  afterward, unwire removes only Sthayi's entry, preserves the other edits, and retains the\n  pre-wire backup.\n- **The housekeeping (consolidation).** Duplicates merge, stale facts fade — every action\n  journaled and reversible.\n- **Keyless core.** Ordinary store, search, write, deterministic consolidation, and MCP operation\n  need zero API keys. Only explicitly invoked Oracle jobs and `sthayi qualify` need a provider key\n  and contact your selected provider. Oracle sends bounded, masked memory batches; `qualify` sends\n  the shipped synthetic conformance fixtures, not user memories.\n- **Lexical FTS5 search** ranked by `bm25 × confidence × recency`. Search is lexical: matching is\n  done by SQLite's FTS5 index over your text. There are no embeddings — no vectors are computed,\n  stored, or queried anywhere in Sthayi, and no model is called to search.\n  `sthayi search <query> --scope <scope>` restricts results to a single scope (e.g. `--scope user`\n  or `--scope project:acme`).\n- **Associative recall (Samskara).** Memories retrieved together wire together: every search\n  strengthens a Hebbian association graph derived purely from the journal, and spreading\n  activation then surfaces memories that share *zero* keywords with your query — keyless and\n  offline. The graph accumulates associations from co-retrievals as you use it. `sthayi index\n  rebuild` re-creates this derived state from the journal bit-for-bit; `--no-assoc` gives you plain\n  lexical ranking.\n- **The oracle proposes; the runtime disposes.** The Oracle is Sthayi's *optional*\n  bring-your-own-LLM memory-consolidation pass: it examines bounded, masked batches of your\n  memories and *proposes* merges, archives, distilled memories, and contradictions — nothing\n  more. Sthayi validates every response against a schema before applying anything, and records\n  each applied change in the journal (one command to roll back). Deterministic consolidation\n  works without any Oracle provider at all.\n\n## Upgrade & uninstall\n\n**Upgrading** never requires rewiring clients: they are wired to the stable launcher\n`~/.sthayi/bin/sthayi-mcp`, not to `npx` or a versioned path. **A launcher pins a pathname, not a\nversion.** It names a Node binary and the CLI entry path it was written from, and it executes\nwhatever file stands at that pathname each time a client starts it — it reads no manifest and\ncompares no version. Upgrade the package **the same way you installed it**: for the headline route\nthat is `npm install -g --prefix \"$HOME/.local\" --engine-strict sthayi@latest`, which replaces\n`~/.local/lib/node_modules/sthayi` in place (or `npm i --engine-strict sthayi@latest` in a local\ninstall directory, whose CLI stays at `./node_modules/.bin/sthayi`). Reinstalling at the same prefix therefore takes\neffect immediately — the entry path\ndoes not move, so both launchers run the new code at the very next client launch, and nothing needs\nrepinning. Your memory is untouched: the data in `~/.sthayi/` is a different directory from the\npackage and survives any reinstall.\n\nOn Windows, upgrade through the same user-space prefix used for installation:\n\n```powershell\n# PowerShell 5.1 or 7\nnpm install -g --prefix \"$env:LOCALAPPDATA\\sthayi\" --engine-strict sthayi@latest\n```\n\n```bat\n:: Windows cmd\nnpm install -g --prefix \"%LOCALAPPDATA%\\sthayi\" --engine-strict sthayi@latest\n```\n\n**Repinning is for an entry path that has moved** — after you move the install, install at a\ndifferent prefix, install by another route, or see a stale pin reported. **Run it from the new\ninstall's own CLI path, never from the launcher in your state directory.** `wire` rewrites both\nlaunchers at the install it is *running from*, and a stale pin is exactly the case where\n`~/.sthayi/bin/sthayi` has stopped working: it names the old entry path, so it can no longer reach\nany code to run. Use the path the route you installed by actually produced:\n\n```bash\n\"$HOME/.local/bin/sthayi\" wire     # the headline route — the shim its --prefix install wrote\n./node_modules/.bin/sthayi wire    # a retained local install, from that directory\n```\n\nOn Windows the same rule, by that route's own path:\n`& \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" wire` in PowerShell, `\"%LOCALAPPDATA%\\sthayi\\sthayi.cmd\"\nwire` in cmd. These forms were included in the v0.1.0 Windows host validation described above.\nDiagnose from the same route's path: use `& \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" doctor` in\nPowerShell or `\"%LOCALAPPDATA%\\sthayi\\sthayi.cmd\" doctor` in cmd. On macOS/Linux, use\n`\"$HOME/.local/bin/sthayi\" doctor` for the headline route. A package problem is fixed by\nreinstalling the prefix, a wiring problem by `wire`, and neither touches your memory.\n\n**Sthayi never copies the package anywhere.** Both launchers reference your install **in place** —\n`~/.local/lib/node_modules/sthayi` on the headline route, and wherever you put it on any other.\nNothing is written under `~/.sthayi/runtime/`; that directory is not created,\nnot refreshed, and not garbage-collected. Sthayi reads it only to refuse it: if a launcher on your\nmachine points at an entry inside `~/.sthayi/runtime/`, `doctor` reports it as a stale runtime pin,\nand `wire` — run from your install's own CLI path, `\"$HOME/.local/bin/sthayi\" wire` on the headline\nroute — repins it at your real install. The directory itself is inert, and\nyours to delete or keep — Sthayi neither removes nor maintains it.\n\n**Uninstalling.** Run the steps that need a working CLI *first*, and run them **by the path of the\ninstall you are about to remove** — the route you installed by, not a default state-directory path\nthat a moved or repinned install may already have made stale. Both `doctor` and `unwire` run from\nthat install, and removing the package takes the launchers' target with it — your install is\nreferenced **in place**, so there is no copy to fall back on:\n\n```bash\n# The headline route's own shim. Installed another way? use that route's path: a retained local\n# install is ./node_modules/.bin/sthayi doctor and ./node_modules/.bin/sthayi unwire; route 2\n# puts `sthayi` on your PATH already.\n\"$HOME/.local/bin/sthayi\" doctor   # 1. read the \"Home directory\" line and write that path down NOW\n\"$HOME/.local/bin/sthayi\" unwire   # 2. remove sthayi from every wired client config\n                                   # 3. remove the PACKAGE — the prefix you installed with:\nnpm uninstall -g --prefix \"$HOME/.local\" sthayi\n                                   #    installed via route 2? then step 3 is: npm rm -g sthayi\n```\n\nOn Windows, run these commands one at a time and stop if `doctor` or `unwire` reports a failure:\n\n```powershell\n# PowerShell 5.1 or 7\n& \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" doctor\n& \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" unwire\nnpm uninstall -g --prefix \"$env:LOCALAPPDATA\\sthayi\" sthayi\n```\n\n```bat\n:: Windows cmd\n\"%LOCALAPPDATA%\\sthayi\\sthayi.cmd\" doctor\n\"%LOCALAPPDATA%\\sthayi\\sthayi.cmd\" unwire\nnpm uninstall -g --prefix \"%LOCALAPPDATA%\\sthayi\" sthayi\n```\n\nStep 3 removes `~/.local/lib/node_modules/sthayi` and the `~/.local/bin/sthayi` shim. It does not\ntouch `~/.sthayi/`, and that is the whole point of the two-directory layout: **your memory outlives\nthe uninstall.** Whether it ends at all is step 4, it belongs to you alone, and Sthayi neither\nperforms nor scripts it — see below for why a printed location is not a verified removal target.\n\n**What step 3 leaves behind: two dangling launchers.** `~/.sthayi/bin/sthayi-mcp` and\n`~/.sthayi/bin/sthayi` — under `$STHAYI_HOME/bin/` when you have set a custom home — live inside\nyour state directory, so no uninstall removes them. After step 3\nboth files are still there, still executable, and still pinned at an entry that is gone — run either\none and it fails at the pathname it names. Step 2 removed the client references to them, so nothing\nlaunches them on your behalf any more; the two files are yours to delete or keep. While a CLI is\nstill available to ask, `doctor` reports a launcher whose pinned entry has gone as a **stale** pin.\nReinstalling and then running `wire` **from the new install's CLI path** repins both at it; deleting\nthe two files ends them.\n\n**Read the `Home directory` line before you rely on it.** Doctor prints one line per check,\nprefixed `✓` or `✗`:\n\n- `✓ Home directory  <path>` — the check passed, and the text is the canonical location of your\n  state directory, with every symlink already resolved.\n- `✗ Home directory  <text>` — the check **failed**, and the text is a diagnostic, not a location.\n  A refusal such as “… is a symlink (possible hijack)” names the path the link resolves to so you\n  can see what is planted there; Sthayi validated nothing and resolved nothing on your behalf, and\n  that path is not a target to act on.\n- **No `Home directory` line at all** — doctor stopped before it got there: the home could not be\n  trusted, the store or key could not be inspected, or there is no store to report on. Nothing\n  about your state directory has been established.\n\nWithout a `✓ Home directory` line, stop, fix what doctor reported, and run it again.\n\n**Removal of the memory itself is a separate, optional decision, and Sthayi does not automate it.**\nStep 3 removes the package only; your memory — db, journal, key — is untouched, and Sthayi retains\nno hosted copy. Sthayi ships no reset or erase command, and this page publishes no procedure for\nerasing a state directory, because a printed location is not a verified removal target:\n\n- `STHAYI_HOME=$HOME` is legal, and then the path doctor prints **is your whole home directory**.\n- So is a filesystem root, a mounted volume, or a network share.\n- So is a directory you already keep your own files in — nothing stops `STHAYI_HOME` pointing at\n  one, and doctor reports it exactly the same way.\n- A `sthayi.db` file inside a directory does not make that directory a Sthayi store: it can be\n  empty or planted, and a directory that holds a store can hold your other files too.\n- A path *string* is not a directory. An unset or mistyped variable, a trailing slash, a `..`\n  segment, or a symlink at any depth all resolve somewhere other than the string reads, and both a\n  recursive delete and a rename follow the resolution, not the string — so string tests like “is\n  it `/`” or “is it `$HOME`” pass on aliases of exactly those directories.\n\nSthayi's own code canonicalizes paths and refuses the applicable symlink, ownership, permission and\ndirectory-identity hazards ([`packages/cli/src/fs-safe.ts`](packages/cli/src/fs-safe.ts)), but it\ndoes not certify a directory as a safe whole-tree removal target. Any non-empty absolute\n`STHAYI_HOME` is a legal state directory\n([`packages/cli/src/paths.ts`](packages/cli/src/paths.ts)), so your OS home, a filesystem, volume\nor share root, and a directory full of your own files each validate exactly like a dedicated one.\nA copy-pasteable one-liner establishes less still, which is why this page carries none.\n\n**Known gap, stated plainly.** The safe form of “remove my memory” is a Sthayi command that\nre-validates the trust boundary and touches only the entries Sthayi itself created — refusing a\nhome that is your OS home, a filesystem/volume/share root, reached through a symlink, or holding\nanything Sthayi did not write. That command does not exist yet, and until it does this page\npublishes no procedure for erasing a state directory. Any removal is an unvalidated action you\ntake yourself, on a directory you have opened and inspected.\n\nUnwire honors the bill of rights above: configs untouched since wire are restored byte-exact,\nconfigs you've edited since lose only the sthayi entry, and a `*.sthayi-bak-*` backup of every\npre-wire config is kept either way. Unwire *first* — removing the package before unwiring leaves\nclients pointing at a launcher whose install is gone. That is recoverable, by the same rule as every\nother repin above: reinstall, then run `wire` **from the new install's own CLI path**. On the\nheadline route that is `\"$HOME/.local/bin/sthayi\" wire` (bash/zsh), because a `--prefix` install\nputs nothing on PATH; from a retained local install it is `./node_modules/.bin/sthayi wire`, run in\nthat directory; on Windows it is the shim that prefix produced —\n`& \"$env:LOCALAPPDATA\\sthayi\\sthayi.cmd\" wire` in PowerShell, `\"%LOCALAPPDATA%\\sthayi\\sthayi.cmd\"\nwire` in cmd. These Windows forms were included in the v0.1.0 host validation. The command name\ntyped on its own reaches the CLI only where a route has already put it on PATH.\n\n## Troubleshooting\n\n**“… is a symlink (possible hijack)” about your home directory.** Sthayi refuses a state directory\nreached through a symlink at *any* depth: a link can be repointed after it is validated, and the db,\nthe key, and the launcher path recorded in every client config would follow it. Some systems hand\nyou exactly that as `$HOME` — `/home -> /usr/home` on several BSDs, or a network-mounted\n`/Users/you -> /net/home/you`. The refusal names the resolved real path; point `STHAYI_HOME` at the\ncanonical location (it must be **absolute** — no `~`, no relative path):\n\n```bash\nexport STHAYI_HOME=\"$(cd ~ && pwd -P)/.sthayi\"   # or: realpath ~/.sthayi · readlink -f ~/.sthayi\n\"$HOME/.local/bin/sthayi\" status                 # the headline route adds nothing to PATH\n```\n\nPut the export in your shell profile so every client launch resolves the same home, then re-run\n`\"$HOME/.local/bin/sthayi\" wire` to record the canonical launcher path in your client configs.\n\n**“NODE_MODULE_VERSION” or “was compiled against a different Node.js version.”** Sthayi's local\nSQLite driver is a native dependency. If you switch between supported Node majors after installing\nSthayi, reinstall the package from the new active Node before running it again. On the headline\nmacOS/Linux route:\n\n```bash\nnode --version   # must begin with v22. or v24.\nnpm install -g --prefix \"$HOME/.local\" --engine-strict sthayi@latest\n\"$HOME/.local/bin/sthayi\" doctor\n```\n\nOn Windows, use the PowerShell or cmd upgrade command in [Upgrade & uninstall](#upgrade--uninstall),\nthen run the matching install-prefix `doctor` command. The reinstall replaces the native module for\nthe active Node ABI; it does not remove or rewrite the separate Sthayi state directory.\n\n## Development\n\n```bash\nnvm use && corepack enable   # Node 22 LTS first, then the pnpm shim that Node ships\npnpm install\npnpm verify                  # lint + typecheck + tests\npnpm dev -- --help           # run the CLI from source\n```\n\nCorepack is a shim that Node itself ships, so switch runtime first: enabling it before `nvm use`\nwires it to whichever Node happened to be active. `.nvmrc` (22) is the runtime development happens\non. The published runtime contract is the explicit set `22.x || 24.x`, not an open-ended minimum:\nCI runs the full verify on Node 22 and Node 24 across Linux, macOS, and Windows.\n\nSee [`CONTRIBUTING.md`](CONTRIBUTING.md) (DCO sign-off required) and\n[`docs/sthayi-v0-spec.md`](docs/sthayi-v0-spec.md) for the full spec and golden invariants.\n\n## Contributing a client adapter\n\nSthayi ships adapters for 14 clients — the `ClientAdapter` interface is public so the community\nadds the next one. The procedure: verify the client's current config format against official docs,\ncapture a fixture under `tests/fixtures/clients/`, implement `detect/isWired/wire/unwire` with\nsurgical edits (jsonc-parser / smol-toml), and back up first. The safety suite must prove both\noutcomes: byte-exact restoration when the config is untouched after wiring, and removal of only\nSthayi's entry while preserving later user edits when it has changed. The non-negotiable rule:\nnever corrupt a user's config.\n\n## Contributing an importer\n\nImporters turn an existing product export into proposed Sthayi memories. Keep the parser pure and\ndefensive: add it beside [the existing ChatGPT parser](packages/core/src/importers/chatgpt.ts). It\naccepts the in-memory `SourceFiles` map, returns `ImportResult`, performs no filesystem or network\naccess, and reports a bad or missing record as a warning rather than crashing the whole import.\n\nWire a new source through all of these points in one pull request:\n\n1. Export the parser from [the core public index](packages/core/src/index.ts).\n2. Add the source and its unambiguous file/shape rules to\n   [source detection](packages/cli/src/importers/detect.ts).\n3. Add it to [import dispatch](packages/cli/src/importers/run.ts); do not bypass the shared archive\n   loader, masking, deduplication, journal, or commit-receipt path.\n4. Add minimal, synthetic fixtures under `tests/fixtures/imports/<source>/` and parser/detection/run\n   tests. Cover a valid export, missing and malformed records, source timestamps, re-import dedupe,\n   warnings, and any fields that could contain secrets or personal data.\n5. Run `pnpm verify`, commit with DCO sign-off (`git commit -s`), and open a PR from your fork as\n   described in `CONTRIBUTING.md`.\n\nNever commit a real user export, credential, conversation, email address, phone number, or other\npersonal data as a fixture. Reviewers will require synthetic data and load-bearing safety tests.\n\n## Good first issues\n\n- **New client adapter** (e.g. Continue) — self-contained, well-documented above.\n- **New importer** — another export format, following `packages/core/src/importers/`.\n- **Prompt-pack improvements** — the `packages/cli/prompts/` conformance suite (ships in the npm\n  tarball) is the community's first surface;\n  improve a prompt and prove it with `sthayi qualify <provider:model>`.\n\n## License\n\n[MIT licensed](LICENSE) © 2026 Gopal Raja · No CLA.\n",
  "bytes": 34969,
  "sha": "651c6536517687d58f5642416c4e6d33fa95a968d8b58b186e19d2779a5c2a39",
  "repo_slug": "sthayi-ai/sthayi",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_sthayi_ai_sthayi_f13fec0c/readme"
}