synaptic-labs-ai/pact-plugin/pact-memory

Claude Code and agent skill by synaptic-labs-ai/pact-plugin

Trust tier 2
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Persistent memory for PACT agents. Save context, goals, lessons learned, decisions, and entities. Semantic search across sessions. Use when: saving session context, recalling past decisions, searching lessons. Triggers: memory, save memory, search memory, lessons learned, remember, recall

Install

npx vskill@latest install synaptic-labs-ai/pact-plugin/pact-memory

SKILL.md

PACT Memory Skill

Persistent memory system for PACT framework agents. Store and retrieve context, goals, lessons learned, decisions, and entities across sessions with semantic search.

Overview

The PACT Memory skill provides:

  • Rich Memory Objects: Store context, goals, tasks, lessons, decisions, and entities
  • Semantic Search: Find relevant memories using natural language queries
  • Graph-Enhanced Retrieval: Memories linked to files are boosted when working on related files
  • Session Tracking: Automatic file tracking and session context
  • Cross-Session Learning: Memories persist across sessions for cumulative knowledge

Store access: the two routes

<!-- PACT_STORE_BAR_BEGIN --> STORE ACCESS. A memory operation (save, search, get, list, update or delete a record) goes through the pact-memory CLI. YOU DO NOT SELECT A STORE. Do not name a store by --db-path, by an environment variable, or by one more route somebody adds later. Let the CLI resolve it. A store you select is not the store the memory of the team lives in, so a save there is lost rather than shared. STORE INSPECTION is different: a row count, a column audit, or a schema check on the file. To inspect, do not run a CLI verb, do not import a module below skills/pact-memory/scripts/, and do not open the store read-write. In ONE command, against ONE resolved path, check that memory.db-wal and memory.db-shm are both absent by their full names, then open with mode=ro and immutable=1. Without immutable=1 the open fails. If a sidecar is present, stop and report. The read does not load the vector extension, so it cannot answer a question about vec_memories. Stop and report rather than take a barred route. <!-- PACT_STORE_BAR_END -->

The sections below give the detail behind each sentence above.

MORE ON THE BRIGHT LINE, because an agent will look for an exception. THE RULE IS A POLICY, AND IT IS NOT A CLAIM ABOUT WHAT THE TOOL DOES. An agent does not select a store. The CLI can tell you to run setup --db-path <path>. That message is correct for the tool and it does not apply to you. You reach it only after you pass --db-path, which this rule forbids. Do not run it. Report it and ask the user. The danger is NOT that the flag reaches the live store. The flag binds the store you name, so the danger is that your save lands in a store nobody reads. For a memory system, a write that goes nowhere costs as much as a write that goes incorrectly.

To inspect the store
  1. Check that memory.db-wal and memory.db-shm are both absent. Name the

two files in full. Do not use a glob.

  1. If one of the two files is present, stop. Report it. Do not read the store.
  2. If neither file is present, open the store read-only:

sqlite3.connect("file:<path>?mode=ro&immutable=1", uri=True)

What you must not do, and why
  • Do not run a pact-memory CLI verb to inspect the store. The CLI opens a

read-write connection and runs PRAGMA journal_mode=WAL on it, which creates memory.db-wal and memory.db-shm. A CLI read is thus a write to the store directory. A CLI run also reaches the same functions an import reaches, so it defeats the next rule.

  • Do not import a module below skills/pact-memory/scripts/. In that package,

functions create the live store directory as a side result of a path resolution, so an import puts each of them one call away. Do not read an absent import as a guarantee, because a subprocess reaches those functions with no import at all.

  • Do not open the store with a plain sqlite3.connect. A read-write open

creates the two sidecar files. That is a write to the store directory, even when no SQL runs.

  • Do not copy the store with cp. A copy taken while commits sit in an

uncheckpointed WAL is silently short of data, and it passes PRAGMA integrity_check. If you must have a copy, use VACUUM INTO.

Why the two flags, and why the check comes first

mode=ro alone cannot open this store. sqlite must create memory.db-shm to read a WAL database, and mode=ro forbids that creation, so the open fails with unable to open database file. immutable=1 tells sqlite to skip the WAL and read the main file directly, so the open succeeds and creates nothing. immutable=1 is not extra hardening. It is the only flag that opens the file.

The sidecar check is not a writer detector. It is a state selector. When the two sidecar files are absent, no WAL data is pending, so the main file is the whole database. That is the state in which immutable=1 is correct. If a sidecar is present, committed data can sit outside the main file, and immutable=1 then returns an older image and raises no error. One flag makes the read possible. The check makes the read correct.

If the check refuses

A refusal is information. In normal operation the CLI closes its connection and sqlite removes the two sidecar files on that close, so the check passes. A sidecar that stays is evidence that a writer did not close cleanly.

If a sidecar is present:

  1. Report the sidecar by its full name and its size.
  2. Do not read the store with immutable=1.
  3. Do not delete a sidecar. A sidecar can hold committed data that is not

in the main file at this time.

  1. Ask the user before you go further. A recovery needs a write, and a write

to this store is the user's decision.

To save a memory

Run the pact-memory CLI save command with no --db-path. The CLI resolves the default store. The section "Store access: the two routes" above gives the cause, and that cause covers a write.

Do not run python3 setup_memory.py init. That script runs as a script, it writes, and it accepts no --db-path, so the write reaches the live store and you cannot steer it away. The pytest refusal in the CLI is keyed on PYTEST_CURRENT_TEST, so it does not cover a run outside pytest.

Do not import a module below skills/pact-memory/scripts/ to write. Most of the modules in that package carry writing SQL.

Quick Start

All commands use the CLI entry point via ${CLAUDE_SKILL_DIR}:

bash
# Save a memory
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" save '{
"context": "Implementing user authentication",
"goal": "Add JWT refresh token support",
"lessons_learned": [
"Redis INCR is atomic - perfect for rate limiting",
"Always validate refresh token rotation"
],
"decisions": [
{
"decision": "Use Redis for token blacklist",
"rationale": "Fast TTL support, distributed access"
}
],
"reasoning_chains": [
"Redis chosen because TTL support → needed for token expiry → simpler than DB cleanup"
],
"entities": [
{"name": "AuthService", "type": "component"},
{"name": "TokenManager", "type": "class"}
]
}'
# See the Memory Structure table below for every field a save payload accepts
# (including agreements_reached and disagreements_resolved). Fields marked
# "never" in that table are read-only and are rejected if you send them.
# Search memories
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" search "rate limiting tokens" --limit 30
# Search with graph-enhanced boosting for current file
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" search "auth tokens" --current-file src/auth/refresh.ts
# List recent memories
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" list --limit 10
# Get a specific memory by full ID or unique prefix (>= 7 chars, case-insensitive)
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" get <memory_id_or_prefix>
# Update an existing memory by full ID or unique prefix (scalar fields replace;
# list fields merge additively). Ambiguous prefix is refused.
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" update <memory_id_or_prefix> '{"goal": "Updated goal"}'
# Delete a memory by full ID or unique prefix. Ambiguous prefix is refused.
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" delete <memory_id_or_prefix>
# Check system status
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" status
# Initialize/verify the memory system
python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" setup

All commands output JSON to stdout: {"ok": true, "result": ...}. Errors output JSON to stderr: {"ok": false, "error": "...", "message": "..."}.

For large JSON payloads (to avoid shell escaping issues), use --stdin:

bash
echo '{"context": "...", "goal": "..."}' | python3 "${CLAUDE_SKILL_DIR}/scripts/cli.py" save --stdin

A bare - in place of the JSON argument is a stdin sentinel (Unix convention): save - and update <id|prefix> - read the payload from stdin, exactly like --stdin. Empty or whitespace-only input on either channel exits 1 with a MISSING_INPUT error.

Memory Structure

A memory record has more fields than a save/update payload accepts. The On save column is the one that governs what you may put in the JSON you pass to the CLI — a payload key outside that set is REJECTED with exit 2 and the memory is NOT written.

FieldTypeOn saveDescription
contextstringyou supplyCurrent working context description
goalstringyou supplyWhat you're trying to achieve
active_taskslistyou supplyTasks with status and priority
lessons_learnedlistyou supplyWhat worked or didn't work
decisionslistyou supplyDecisions with rationale and alternatives
entitieslistyou supplyReferenced components, services, modules
reasoning_chainslistyou supplyHow key decisions connect — "X because Y, which required Z"
agreements_reachedlistyou supplyWhat was verified via teachback or agreement check
disagreements_resolvedlistyou supplyWhere agents disagreed and how it was settled
project_idstringoptionalAccepted in the payload; auto-detected from the environment when you omit it
session_idstringoptionalAccepted in the payload; auto-detected from the environment when you omit it
fileslistneverRead-only. Returned by get/search/list; REJECTED as a payload key — see below
files is read-only — do not put it in a save payload

files is part of a memory RECORD, not of a save PAYLOAD. It is stored in a separate link table and re-attached when a memory is read back, so you will see it in get / search / list output. Passing it to save or update fails with exit 2 and writes nothing.

The CLI has no way to set it: there is no --files flag, and the automatic session-file linking runs off in-process state that a fresh CLI invocation never has. For a CLI-created memory, `files` is always empty. Only a long-lived in-process caller of the Python API can populate it, via the separate files= parameter of MemoryAPI.save() — never a payload key.

To record which files a memory concerns, name them in an entity's notes field instead.

save refuses when no project identity resolves

If no project identity can be resolved, save refuses with ProjectIdentityUnresolvedError, a ProjectScopeDisagreementError subclass. The CLI surfaces it as exit 1 with PROJECT_IDENTITY_UNRESOLVED on stderr, and nothing is written. An actual disagreement between CLAUDE_PROJECT_DIR and the session record uses SCOPE_DISAGREEMENT instead.

To proceed, supply project_id explicitly in the payload. A supplied project_id must be a non-empty string without C0, DEL, or C1 control characters (U+0000-U+001F, U+007F-U+009F). Other Unicode, including ordinary spaces, is allowed. Invalid values exit 2 and write nothing.

When no project identity resolves, list, search, and search_by_file return empty results, and status reports zero project-scoped counts. These results do not prove that the store has no memories; resolve the project identity before interpreting them.

Task Format
python
{"task": "Implement token refresh", "status": "in_progress", "priority": "high"}

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
48
Repository forks
11
7-day trend score
19

Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 19 Mar 2026, 7 months ago.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/synaptic-labs-ai/pact-plugin/pact-memory/badge)](https://verified-skill.com/skills/synaptic-labs-ai/pact-plugin/pact-memory)

Something wrong with this skill or its page? Tell us.