slm-remember-a85a7b — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited slm-remember-a85a7b (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Store atomic, durable facts into SuperLocalMemory for retrieval in future sessions. One fact per call. Recall before you remember.
Store:
Do not store:
remember. It stores text. A screenshot, photo orPDF goes through remember_media or remember_document; see slm-media. Add the reason it matters in the text of a normal memory if you also want a fact about it.
Before calling remember, always call recall first with the core terms of what you are about to store. If a near-duplicate exists:
that changed, a rule that was reworded), save it with remember(..., replaces="<fact_id>"). It takes effect at once and can be undone.
change, use update_memory(fact_id, content). This opens a correction for review; it does not overwrite anything (see "Updating a memory" below).
remember with neither when no sufficiently similar fact is found.Duplicates degrade retrieval quality for every future session.
recall(query="JWT token expiry auth", limit=5, session_id="<sid>")If a near-duplicate is returned:
remember(
content="JWT tokens use 1h expiry for API access tokens; refresh tokens 30d",
tags="auth,security,decision",
project="superlocalmemory",
kind="decision",
replaces="f8a2bc91",
)The old memory is retired, not deleted: recall stops returning it and it is no longer loaded at session start. The response's replaced says what was retired, or why nothing was (the new memory is saved either way). An unknown id, or an id from another profile, is refused before anything is saved.
remember(
content="Decided to use JWT with 1h expiry for API auth; refresh tokens persist 30 days",
tags="auth,security,decision",
project="superlocalmemory",
importance=8,
session_id="<sid>",
)Real response shape:
{
"success": true,
"fact_ids": ["c9d4e112"],
"count": 1,
"pending": false,
"pending_id": null,
"operation_id": "op-7c21",
"materialization_state": "complete",
"message": "Stored through canonical daemon ingestion."
}pending: true with materialization_state queryable or enriching means the memory is already stored and findable by its words while enrichment finishes; do not re-save. A reply with materialization_state: "accepted" and count: 0 means the memory is durable but the writer was busy; it becomes searchable within seconds, and resending the same idempotency_key returns the final receipt. When the call used replaces the reply carries replaced; when the same words were already saved under another confirmed kind it carries kind_conflict and keeps that kind.
Failures come back as success: false with a code and retryable: DAEMON_UNAVAILABLE (retryable: true), INVALID_KIND, NOT_AUTHORIZED, or an unknown-profile / unknown-replaces refusal (retryable: false).
Never claim "saved" unless `success: true` is in the response.
remember(
content: str, # required — the atomic fact to store
tags: str = "", # comma-separated tags, e.g. "auth,security,gotcha"
project: str = "", # project scope, e.g. "superlocalmemory"
importance: int = 5,# 1–10; see scale below
session_id: str = "",# from session_init; attributes the write to this session
session_date: str = "",# when the memory is ABOUT, if not today
scope: str = None, # "personal" (default) | "shared" | "global"
shared_with: str = "",# comma-separated profile_ids for scope="shared"
idempotency_key: str = "",# replaying the same key will not store a second copy
kind: str = "", # what sort of memory this is; see "Say what kind it is"
replaces: str = None,# fact_id (or memory_id) of the earlier memory this one replaces
profile_id: str = "",# write to another existing profile; "" = the active one
agent_id: str = "mcp_client", # attribution; resolved from the connection when left alone
)Multi-scope (opt-in): leavescopeunset forpersonal(private to this profile — the default, the same as a single-profile install)."global"is visible to every profile on the machine;"shared"is visible to the profiles inshared_with. See docs/shared-memory.md.
importance scale:
Use 7–10 only for facts that would cause real damage if forgotten.
session_date says when the memory is about, as distinct from when you wrote it. Omit it and the memory is dated today.
remember(
content="The outage on the payments queue was caused by a stale DNS entry",
tags="incident,payments,postmortem",
project="platform",
session_date="2026-08-14", # YYYY-MM-DD, or a full ISO 8601 timestamp
session_id="<sid>",
)Use it whenever you are writing something down after the fact — a postmortem, a decision taken in a meeting last week, a migration that ran on a known date. Time-filtered recall (window="7d", window="2026-07-01..2026-07-31") reads event time, so a mis-dated memory is one a time-scoped question cannot find.
session_date does not change what kind of memory it is. A memory that describes something planned — "the migration is scheduled for Tuesday", "the certificate expires on 2026-09-01" — is stored as a prospective memory, and recall reports it as "fact_type": "prospective". That is inferred from how the content reads, not from the date you pass. Older stores spelled this type "temporal"; that value still reads correctly and needs nothing from you.
kind is one of nine values: rule (a standing instruction: "always/never ..."), decision (a choice that settles a question), status (the current state of something, which a later update will replace), procedure (steps or commands), prospective (a plan or to-do), opinion (a preference or view), correction (says an earlier memory was wrong), episodic (something that happened) or semantic (a lasting fact). An unknown value is refused with INVALID_KIND before anything is saved.
Set it whenever you know. A kind you declare is confirmed, and confirmed rules (up to 10) and confirmed decisions (up to 5) are loaded by session_init at the start of later sessions. Leave kind empty when unsure: SLM may suggest one later, and a suggestion changes nothing until someone confirms it. Never set a kind just to get a memory loaded at session start.
Manage kinds after the fact:
| Tool | Use |
|---|---|
set_memory_kind(fact_id, kind) | Set and confirm the kind of one memory you know the type of |
review_memory_kinds(kind="", limit=20) | List suggestions waiting for confirmation (limit 1–100) |
confirm_memory_kinds(items) | Confirm up to 200 at once; each item is {"fact_id": ..., "kind": ...}, and omitting kind accepts the suggestion |
memory_kinds_status() | Counts per kind, the classifying backend, any run in progress |
CLI: slm remember "<text>" --kind rule, slm kinds status|set|review|confirm, slm kinds backfill start|pause|resume|cancel|revert|status, and slm kinds settings (backend, standing rules on or off). Classifying with Jev sends memory text online and needs its own consent (--jev-consent yes).
replaces versus update_memoryupdate_memory(fact_id, content) and slm update <fact_id> "<new text>" do not overwrite a memory. They keep the original and propose a correction: the reply has predecessor_fact_id, successor_fact_id, correction_case (with case_id, status, version) and review_required: true. Until a person applies the case, the original stays current and the new text is not returned by recall. A memory can have only one open correction at a time; a second edit is refused with a message naming the open case.
Review cases with list_corrections(limit=100) and review_correction(case_id, action, expected_version), where action is apply, reject or rollback and expected_version is the case's current version. apply retires the original and admits the new text; rollback undoes an applied case (including one made by replaces). CLI: slm review-correction <case_id> apply|reject|rollback <expected_version>.
Two rules about SLM's own guesses. When it saves a memory that looks like an update to an older one, it may file a correction case of its own. That guess never hides the memory you saved: both stay findable until a person reviews it, approving retires the older one, and rejecting keeps both. And if you edit, replace or delete a memory that only such an unreviewed machine guess names, your action wins and the guess is closed as overtaken (slm corrections overtaken lists them, slm corrections restore-overtaken <case_id> puts one back). A correction a person proposed, or one already decided, is kept permanently and protects the memories in it from being deleted.
Store one atomic fact per remember call. Do not concatenate multiple unrelated points into a single content string — they will be hard to update individually and harder to retrieve cleanly. If you have three separate decisions, make three calls.
Untagged, unscoped facts are harder to retrieve and harder to manage. Minimum: set tags to one or two relevant terms and project to the repo/product name.
The MCP forget(dry_run=True) tool runs an Ebbinghaus decay cycle over the whole profile — it does NOT delete by query. To delete one memory you have the id of, call delete_memory(fact_id). To delete by query, use the CLI:
# Preview what would be deleted (always do this first)
slm forget "<query>" --dry-run [--json]
# Execute deletion after confirming the preview
slm forget "<query>" --yes [--json]
# Delete a specific fact by exact ID (use when you have the fact_id)
slm delete <fact_id> --yes [--json]Flags verified in source (main.py):
slm forget: positional query, --dry-run, --yes / -y, --jsonslm delete: positional fact_id, --yes / -y, --jsonAlways run --dry-run first and review the preview before passing --yes. A memory that belongs to a reviewed correction cannot be deleted (it is refused with the case ids and nothing is changed). Treat every other deletion as permanent.
# Store a fact
slm remember "<content>" [--tags a,b,c] [--kind rule|decision|...] [--json]
# Replace an earlier memory (takes effect at once; undo with review-correction)
slm remember "<content>" --replaces <fact_id> --kind status
# Store a shared/global fact (opt-in)
slm remember "<content>" --scope global
slm remember "<content>" --scope shared --shared-with alice,bob
# Propose a reviewed correction instead of replacing
slm update <fact_id> "<new text>"
slm review-correction <case_id> apply|reject|rollback <expected_version>
# Flags: --tags, --kind, --replaces, --json, --sync, --scope, --shared-with
# --sync: wait for full enrichment before returning (default is async)
# --scope: personal (default) | shared | global ; --shared-with: profile ids for sharedFlags that do NOT exist on slm remember: --importance, --project, --format — these are MCP-only params or fabricated.
| Scenario | Action |
|---|---|
| Fact has changed and the new version should win now | remember(..., replaces="<fact_id>") |
| Fact needs a correction a person should approve | update_memory(fact_id, new_content), then review_correction |
| Duplicate found that matches recall result | replaces the existing one, or leave it |
| Fact is wrong and should disappear | slm forget "<query>" --dry-run then --yes |
| Fact has a known ID and is clearly obsolete | delete_memory(fact_id) or slm delete <fact_id> --yes |
Every remember call defaults to personal scope — private to the active profile. To share a fact with other profiles on the same machine, set the scope parameter:
# Share with every profile on this machine
remember(
content="API rate limit is 100 req/min per tenant",
tags="api,limits,shared",
project="platform",
scope="global", # visible to all profiles
session_id="<sid>",
)
# Share with specific profiles only
remember(
content="Staging DB migration runs Fridays 22:00 UTC",
tags="db,ops",
scope="shared",
shared_with="work-profile,devops-profile",
session_id="<sid>",
)Only set scope when the user explicitly asks to share. The default personal scope is identical to single-profile SLM. See slm-scope for the complete sharing model and when to use each scope.
remember stores in the active profile. To write one memory to another existing profile, pass profile_id="<name>"; an unknown name is rejected, never created. switch_profile moves the active profile for every later call and for other sessions on this machine, so use it only when the user asks to move. See slm-profile.
slm-recall — retrieve what was rememberedslm-session — session lifecycle; session_id is required for attributionslm-scope — complete guide to personal / shared / global scopesslm-profile — workspace isolation and profile switchingslm-media — saving pictures and PDFs (remember_media, remember_document)SuperLocalMemory v4.2.11 · Qualixar · AGPL-3.0-or-later
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.