subrosa
Health Uyari
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Basarisiz
- rm -rf — Recursive force deletion command in hooks/run.sh
- rm -rf — Recursive force deletion command in install.sh
- rm -rf — Recursive force deletion command in scripts/bench.sh
- rm -rf — Recursive force deletion command in scripts/demo-data.sh
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Persistent, private memory for Claude Code — every session archived locally, searchable. Sub rosa.
Persistent, private memory for Claude Code — that never spends your tokens on itself.
Every session is archived into a local SQLite database and becomes searchable: the work you did last month is one subrosa search away, relevant past sessions resurface automatically when you type a related prompt, and Claude stops rediscovering things it already figured out. That last part is where it pays for itself: pulling up last month's answer costs a few hundred tokens, while having Claude re-derive it from scratch — re-reading files, redoing the investigation — runs into the thousands.
- No LLM calls to save memory. Saving a session is plain text parsing — it never spends tokens. Most memory plugins run your sessions through an LLM to save them; the comparison has the numbers, from their own docs.
- Hard token limits, set in the code. Recall adds ~180 tokens to a prompt on a strong match, and usually nothing — it stays silent otherwise. The always-loaded index is capped at 23 KB. Check it yourself, or see where your tokens go, step by step.
- One 3.7 MB static binary. No daemon, no worker port, no background process. A hook fires, finishes in under 10 ms, and exits.
- Your transcripts stay on your machine. The binary makes zero network calls — no cloud, no telemetry — and obvious secret shapes are masked before storage. Don't take my word for it: verify every claim yourself.
Why "subrosa"? ·
Quick start ·
What it does ·
Commands ·
The memory workflow ·
Make Claude search the archive itself
Where your data lives ·
Privacy model ·
Proof ·
Performance ·
Development ·
How it compares ·
FAQ
Why "subrosa"?
In ancient Rome, a rose hung over the table meant everything said under it stayed in the room — sub rosa, "under the rose." That's the contract this tool makes with your data: every transcript stays on your machine, in a local database, with obvious secret shapes masked before they're stored. No cloud, no telemetry — what's said under the rose stays under the rose.
Quick start
Inside Claude Code, run these two commands:
/plugin marketplace add ij5a/subrosa
/plugin install subrosa@subrosa
Then start a new Claude Code session (quit and reopen, or run claude again). That's the whole install:
- On that first start, the plugin downloads the right prebuilt program for your computer (about 2 MB, checksum-verified against this repo) and archives every Claude Code session already on your disk.
- From then on it runs by itself: each session is archived when it ends, related past sessions are shown to Claude when you type a prompt, and you get a short note when ended sessions are waiting to be saved into long-term memory.
The one-time download fetches the program itself — your data never goes anywhere.
Then one more command, in your terminal, for the best experience — it teaches Claude to
search the archive at the start of any task, instead of waiting for you to ask
(what it adds — safe to run twice, ~150 tokens):
~/.claude/subrosa/bin/subrosa init --claude-md # or just: subrosa init --claude-md, with the CLI below
Optional: the subrosa command in your terminal
The plugin works without this. Install the CLI if you also want to search and manage the archive yourself:
# homebrew
brew install ij5a/tap/subrosa
# or the install script (prebuilt, checksum-verified)
curl -fsSL https://raw.githubusercontent.com/ij5a/subrosa/main/install.sh | sh
# or from source, if you have Rust
cargo install --git https://github.com/ij5a/subrosa
The plugin finds a binary on PATH and uses it, so both stay in sync. Two useful first commands:
subrosa setup # one-time: pick where backup snapshots mirror to (iCloud / Dropbox / ... / none)
subrosa # the dashboard
What it does
- Archives every session. When a session ends — quitting Claude Code, running
/clear, or logging out all count — the plugin saves its transcript into a local database (SQLite with full-text search), and catches up on anything it missed at the next start. - Recalls on its own. When you submit a prompt with enough distinctive terms, the top matching past sessions from the same project are injected into context — quiet unless the match is strong.
- Builds long-term memory. Ended sessions wait in a queue; the bundled
/subrosa:checkpointand/subrosa:checkpoint-backlogcommands read them and save the important points as curated facts (one fact per small markdown file).subrosa generatethen buildsMEMORY.md— a short index Claude Code loads every session, capped in size so it can never overflow. - Makes everything searchable.
subrosa search <terms>runs ranked full-text search, so identifiers likemy-app-prodorTICKET-123stay searchable — with--fuzzyfor partial names and typos. - Shows what clusters together.
subrosa related <identifier>ranks the terms and past sessions that keep showing up alongside something likeauth.tsorTICKET-123— read from the archive, not guessed. It answers "what did this work touch," whichsearchcan't. - Follows your curated links. Memory notes can point at each other with
[[name]]links;subrosa fact link <slug>lists what a note links to and what links back, and flags any link to a note that doesn't exist. - Shows you the picture.
subrosaalone prints the dashboard: activity sparkline, store size, per-project share, index budget. - Backs itself up. Consistent snapshots on a 24h throttle, plus an optional mirror of the latest snapshot to a folder you pick.
- Masks secrets at the door. Private key blocks, AWS keys, bearer tokens, and
password=-style values are redacted before they're written.
Commands
subrosa # dashboard (same as: subrosa stats)
subrosa search aurora failover # find that thing from three weeks ago
subrosa search --project api deploy # scope to one project
subrosa search -n 30 --raw 'cache OR redis'
subrosa search --fuzzy ratelimiter # substring/typo matching (builds a trigram index on first use)
subrosa related cache-prod # terms + sessions that co-occur with an identifier
subrosa related TICKET-123 --project api # what clustered around it, scoped to one project
subrosa fact list # curated facts for the current project
subrosa fact upsert --leaf note.md # add/update a fact from a markdown file (one fact per file)
subrosa fact link auth-decision # show [[name]] links into/out of a fact (flags dead links)
subrosa generate # rebuild MEMORY.md (byte-budgeted)
subrosa import ~/.claude/projects/<project>/memory # one-time import of an existing MEMORY.md
subrosa session <id> # dump one archived session (full id or unique prefix)
subrosa pending # sessions queued for checkpointing
subrosa checkpoint-drop <id> # de-queue one session after saving it
subrosa sweep # catch up on changed transcripts
subrosa backup --force # snapshot now
subrosa setup # one-time backup-mirror question
The memory workflow
flowchart TD
ended["session ends<br/>quit, /clear, or log out"] --> archived["archived into the local database<br/>+ queued for checkpoint"]
archived --> nudge["next session start<br/>a note lands in Claude's context:<br/>N sessions queued for checkpoint"]
nudge --> backlog["/subrosa:checkpoint-backlog<br/>saves durable facts from each queued session"]
livesession["live session<br/>before /clear or /compact"] --> checkpoint["/subrosa:checkpoint<br/>saves durable facts from the current session"]
backlog --> facts["curated facts<br/>one file per fact + the facts database"]
checkpoint --> facts
facts -->|subrosa generate| memorymd["MEMORY.md<br/>byte-budgeted, loaded every session"]
archived -.->|stays searchable either way| recall["subrosa search + automatic prompt recall"]
- A session ends (you quit Claude Code, run
/clear, or log out) → it's archived and queued. - At the next session start, a note lands in Claude's context:
[subrosa] N session(s) queued for checkpoint…— hook output goes to Claude, not to your chat window, so Claude acts on it (or you can run the next step yourself). - Run
/subrosa:checkpoint-backlog— Claude reads each queued session and saves the important facts into that project's memory (one file per fact, plus the facts database), then rebuildsMEMORY.md. - Before
/clearor/compact, run/subrosa:checkpointto do the same for the live session.
MEMORY.md is generated from the facts table under a byte budget — important facts (pinned, feedback) win when space runs out, and everything that doesn't fit stays searchable in the archive.
Make Claude search the archive itself
Recall only fires when you type a prompt. To have Claude check the archive at the
start of any task on its own, add one paragraph to your CLAUDE.md: ~/.claude/CLAUDE.md
covers every project, a repo's own CLAUDE.md just that one. Paste and adjust:
## Memory recall (subrosa)
Every past Claude Code session is archived locally and searchable with
`subrosa search "<keywords>"` — scope with `--project <name>`, more results with
`-n 20`, and retry with `--fuzzy` if an exact search finds nothing (partial names, typos).
(If `subrosa` isn't on PATH, it's at `~/.claude/subrosa/bin/subrosa`.)
At the start of any task — investigating, debugging, designing, reviewing, or when
a ticket, environment, resource, person, or past decision comes up — search the
archive first and build on what past sessions already worked out instead of
starting cold. Announce the search ("Searching past sessions for [topic]...") and
cite hits with their date. Skip only for trivial one-liners. `MEMORY.md` is
generated — never hand-edit it; update facts with `subrosa fact` + `subrosa generate`,
or run `/subrosa:checkpoint`.
Or have it appended for you — same text, idempotent, and a no-op if the section
is already there:
subrosa init --claude-md
subrosa never edits your CLAUDE.md without asking: this instruction adds about
150 tokens that load every session, so spending them is your call. In return,
Claude writes its own searches mid-task and follows leads that prompt-triggered
recall can't see.
Where your data lives
| What | Where | Why |
|---|---|---|
| Live database | ~/.claude/subrosa/memory.db |
Not in synced folders — cloud sync corrupts a live SQLite database (its WAL/SHM helper files) |
| Snapshots | ~/.claude/subrosa/backups/ |
Last 7 kept, owner-only permissions |
| Mirror | the folder you picked in subrosa setup |
A single static snapshot file is safe to sync |
| Checkpoint queue | ~/.claude/subrosa/pending-checkpoint.log |
Plain text, one session per line |
Everything is overridable with env vars: SUBROSA_DIR, SUBROSA_DB, SUBROSA_PROJECTS_DIR, SUBROSA_PENDING_LOG, SUBROSA_MIRROR.
Privacy model
- Local-only. The binary makes zero network calls; recall reads only your local database, and hook output goes only into your own session.
- Recalled snippets are your own archived text resurfaced verbatim — the injection block tells Claude to verify before relying on them.
- The database is readable only by you (
0600), and so is its folder (0700). - Secret shapes are redacted before storage. The source transcripts under
~/.claude/projectsremain as Claude Code wrote them — full-disk encryption is the real at-rest control for those. - Two things touch the network, neither is the binary and neither carries your data out: the plugin's one-time bootstrap downloads the program from GitHub releases (checksum-verified, uploads nothing), and the optional backup mirror copies a snapshot file into a folder you pick — if you pick an iCloud/Dropbox-synced folder, your sync client uploads it. Your call, off by default.
Proof: verify it yourself
Claims are only worth the commands that check them. Everything below runs against this repo or your own install — the whole thing is ~5,200 lines of Rust, MIT licensed, small enough to read in an afternoon.
| Claim | Check it | What you'll see |
|---|---|---|
| The token limits are constants in the code | read MAX_INJECT + SNIPPET_CHARS in src/recall.rs, and DEFAULT_BUDGET in src/generate.rs |
MAX_INJECT = 3, SNIPPET_CHARS = 160 (a match-centered snippet, hard-capped at 160 chars ≈ 180 tokens at recall), and a 23 KB index budget — values you can read, not settings that can drift |
| Recall stays near ~180 tokens a prompt | scripts/bench.sh — the recall injection line |
the injected block weighed in bytes → ~170 tokens on a strong match (3 snippets); the MAX_INJECT × SNIPPET_CHARS cap holds it there |
| The binary makes zero network calls | cargo tree -e normal | grep -Ei 'reqwest|hyper|tokio|rustls|openssl|curl' |
no output — there's no HTTP or networking library in the build. For runtime proof, trace it: strace -f -e trace=network subrosa search x (Linux) or sudo dtruss -t connect subrosa search x (macOS) records no connect() |
| Secrets are masked before storage | cargo test redact |
the round-trip tests pass; redaction runs on the one write path (src/ingest.rs), so the database and its index only ever hold the masked copy |
| The archive is locked to your user | ls -ld ~/.claude/subrosa && ls -l ~/.claude/subrosa/memory.db |
drwx------ (0700) on the directory, -rw------- (0600) on the database |
| The supply chain is small and audited | cargo tree --depth 1 · cargo audit |
5 direct dependencies, no known advisories. CI runs cargo audit on every push, and release binaries ship a sha256sums.txt that the installer and Homebrew formula pin |
| Nothing runs in the background | ps aux | grep subrosa between prompts |
nothing — every hook is a short-lived process that opens the database, does its work, and exits |
What it does not protect
- Redaction matches known shapes — it's not a full clean-up. It hides private-key blocks, AWS keys (starting with
AKIAorASIA),Bearertokens, and labeled secrets likepassword=ortoken:. A secret that doesn't fit one of those patterns — a GitHubghp_…token, an OpenAIsk-…key, a bare JWT — is stored as written. It cuts down obvious leaks; it doesn't remove them all. - Your original transcripts stay in cleartext. Claude Code writes them under
~/.claude/projectsand subrosa never edits those — redaction only covers its own archive copy. Full-disk encryption is the real at-rest control. - Recall re-injects your own stored text. On a strong match it puts up to 3 short snippets back into the model's context, so anything that did leak into the archive can resurface there. The injection block tells Claude to treat it as unverified.
0600/0700is access control, not encryption — and it's enforced on Unix only; on Windows the files fall back to default ACLs.- One snapshot can leave the machine, by your choice. The optional backup mirror (
subrosa setup, off by default) copies a snapshot to a folder you pick; aim it at an iCloud/Dropbox folder and your sync client uploads it. The live database is never synced. - Three small
unsafeblocks, all libc calls for terminal width andSIGPIPE(src/stats.rs,src/main.rs), each with a safety note, none in the data path.grep -rn unsafe src/shows all three.
Performance
A hook that runs on every prompt has to be invisible. Measured with scripts/bench.sh
(hyperfine, synthetic 50,000-turn / 28 MB archive, Apple M3 Max):
| Operation | Time |
|---|---|
| Prompt recall check, no match — the usual case | ~4 ms |
| Prompt recall check, match found and injected | ~14 ms |
| A full hook fire as Claude Code runs it (shell wrapper + binary) | under 10 ms |
| Session-start catch-up sweep, nothing changed | ~5 ms |
subrosa search over 50,000 turns |
5–11 ms |
subrosa related <identifier> over 50,000 turns |
0.3–0.4 s |
| Archiving 50,000 turns from scratch (first install) | ~1.1 s |
One static 3.7 MB binary, no background process, no runtime dependencies. Reproduce
the numbers with scripts/bench.sh (needs hyperfine).
Development
mise install # pinned Rust toolchain (mise.lock)
git config core.hooksPath .githooks # once per clone: sweep + fmt + clippy + tests on commit
cargo build && cargo test
The output formats (stored text, session dump, MEMORY.md, recall block) are pinned byte-for-byte by the golden tests in tests/ — a failing golden test means a format change that needs a deliberate decision. Point everything at a throwaway dir so you never touch your live data:
SUBROSA_DIR=/tmp/x SUBROSA_PROJECTS_DIR=/tmp/x/projects cargo run -- init
License
MIT
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi