{"id":"5ab4408e-3cd6-4ab2-9f85-c09dc4ce36a8","entityType":"agent","slug":"clawhub-hughpyle-keep","name":"Reflective Memory","canonicalUrl":"https://www.xpersona.co/agent/clawhub-hughpyle-keep","canonicalPath":"/agent/clawhub-hughpyle-keep","generatedAt":"2026-10-09T13:29:59.264Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-09T08:19:07.107Z","emptyReason":null},"description":"Reflective Memory Skill: Reflective Memory Owner: hughpyle Summary: Reflective Memory Tags: latest:0.109.0, v0.8.1:0.8.1 Version history: v0.109.0 | 2026-03-24T11:19:23.501Z | auto Major update with expanded API, flow-based operations, and enhanced documentation. - Introduces new flow-based API (keep_flow, keep_prompt, keep_help) with standardized parameters for all operations. - Protocol Block now uses flow and prompt tool calls inst","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 3.4K downloads reported by the source. Last updated 10/9/2026.","installCommand":"clawhub skill install s174stemh4f7w68eeqj22y15c583etgc:keep","sourceUrl":"https://clawhub.ai/hughpyle/keep","homepage":"https://clawhub.ai/hughpyle/skills/keep","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/hughpyle/keep","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/hughpyle/skills/keep","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":66,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Reflective Memory Skill: Reflective Memory Owner: hughpyle Summary: Reflective Memory Tags: latest:0.109.0, v0.8.1:0.8.1 Version history: v0.109.0 | 2026-03-24T"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-09T08:19:07.107Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T08:19:07.107Z","emptyReason":null},"stars":null,"forks":null,"downloads":3392,"packageName":null,"latestVersion":"0.109.0","tractionLabel":"3.4K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-09T08:19:07.107Z","emptyReason":null},"lastUpdatedAt":"2026-10-09T08:19:07.107Z","lastCrawledAt":"2026-10-09T08:19:07.107Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-10T08:19:07.107Z","lastVerifiedAt":null,"highlights":[{"version":"0.109.0","createdAt":"2026-03-24T11:19:23.501Z","changelog":"Major update with expanded API, flow-based operations, and enhanced documentation. - Introduces new flow-based API (`keep_flow`, `keep_prompt`, `keep_help`) with standardized parameters for all operations. - Protocol Block now uses flow and prompt tool calls instead of direct CLI commands; protocol integrated as a workspace-local file. - Adds support for linking provenance of notes and documents using `informs` / `informed_by` tags. - Documented tools, parameters, and search steering mechanisms including temporal filtering and relevance bias. - Extensive new documentation and CLI/flow usage references; onboarding and guidance materials significantly updated. - System integration models updated (MCP, CLI parity, OpenClaw, Claude Code, Kiro, Codex compatibility).","fileCount":319,"zipByteSize":2876294},{"version":"0.43.5","createdAt":"2026-02-16T12:49:13.290Z","changelog":"- Added hosted-service support: you can now use keepnotes.ai by setting the `KEEPNOTES_API_KEY` (local provider setup is now optional). - Expanded system and documentation with additional speech-act status tags (e.g., blocked, declined, fulfilled, open, renegotiated, withdrawn). - Introduced new speech-act type tags (assertion, assessment, commitment, declaration, offer, request) for improved tagging and reflection workflows. - Added security workflow and dependabot configuration for improved maintenance. - Documentation updates: clearer quickstart/setup instructions and new guides (e.g., `KEEP-ANALYZE.md`).","fileCount":116,"zipByteSize":415148},{"version":"0.38.4","createdAt":"2026-02-13T17:16:02.104Z","changelog":"- Added support for moving \"now\" history with the new `keep move` command, allowing archiving and topic-based extraction of intention strings. - Introduced system-level metadata for albums, artists, and genres. - Added new backend, protocol, and remote modules to enhance architecture and future provider integrations. - Expanded test coverage with new tests for concurrency, media types, meta resolution, migrations, and recovery. - Documentation improvements: new guides for move operations (`KEEP-MOVE.md`), configuration, and architecture. - Various enhancements, refactors, and bugfixes across core modules and documentation.","fileCount":99,"zipByteSize":385125},{"version":"0.31.0","createdAt":"2026-02-11T21:10:54.003Z","changelog":"Version 0.31.0 introduces extensive documentation improvements and enhanced reference material. - Added comprehensive documentation files covering configuration, commands, output, tagging, and versioning. - Expanded and updated guides for core commands and APIs: see docs/ for KEEP-CONFIG, KEEP-FIND, KEEP-GET, KEEP-LIST, KEEP-NOW, KEEP-PUT, OUTPUT, TAGGING, and VERSIONING. - Updated existing docs (README.md, AGENT-GUIDE.md, PYTHON-API.md, REFERENCE.md) for clarity and completeness. - Multiple code files changed for alignment with new documentation and reference standards. - Internal improvements to support new documentation structure.","fileCount":86,"zipByteSize":343576},{"version":"0.30.2","createdAt":"2026-02-11T18:29:57.037Z","changelog":"**Summary:** This release features major documentation updates, internal reorganization, and test cleanup. - Documentation overhauled: clearer instructions, quickstart improvements, more precise guidance for tool integrations and first-time setup - SKILL.md rewritten: expanded explanations, condensed protocol block, improved clarity on practice and reference commands - File organization changed: OpenClaw plugin files moved under keep/data/openclaw-plugin/ - Tests cleaned up: outdated or redundant tests removed, new test_review_fixes.py added - Minor code and config tweaks in alignment with updated docs and restructured content","fileCount":77,"zipByteSize":339353},{"version":"0.27.1","createdAt":"2026-02-09T02:40:35.808Z","changelog":"- Added detailed guidance on installing and integrating the keep Protocol Block for persistent reflective practice across projects and agent frameworks. - Described OpenClaw plugin and cron-based daily reflection integration for automated context injection and deep self-review. - Expanded explanation of the reflective memory practice, including the philosophy behind reflection, conversation types, and value of breakdowns. - Provided clearer instructions for first-time setup, document indexing, and environmental variable configuration. - Reorganized structure for easier navigation and practical adoption of reflection in daily work.","fileCount":80,"zipByteSize":340309},{"version":"0.20.0","createdAt":"2026-02-07T17:48:21.604Z","changelog":"**Summary:** Major update with deeper reflection practices, streamlined protocol, enhanced documentation, and new infrastructure. - Overhauled SKILL.md to clarify and condense the core reflective protocol and practice. - Added guided reflection flow: `keep reflect` now supports structured reflection sessions. - Expanded documentation: new guides (releasing, quickstart, architecture, integrations). - Automatic installation of protocol block and session hooks for supported tools. - Enhanced configuration, tagging, and domain organization strategies. - Significant internal changes: added new modules, updated test suite, improved integration structure.","fileCount":75,"zipByteSize":329601},{"version":"0.8.1","createdAt":"2026-02-04T02:51:30.721Z","changelog":"**Major update with enhanced self-presence, system document integration, and workflow improvements:** - Introduced Layer 0: self-installing protocol block and global presence instructions for continued reflective practice across sessions and agents. - Replaced embedded pattern documents with internal system docs (`_system:conversations`, `_system:domains`) and moved library content into dedicated `docs/library/`. - Improved flow and clarity in the practice guide; updated example commands to use new CLI features (`keep now`, `keep get ... --similar`, etc.). - Added persistent version history and context tracking commands; clarified discovery via similar items. - Updated install instructions, metadata, and quickstart to match new package structure and local model support. - Removed obsolete patterns, test fixtures, and replaced references with new internal resources.","fileCount":66,"zipByteSize":296567}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s174stemh4f7w68eeqj22y15c583etgc:keep","setupComplexity":"low","setupSteps":["Setup complexity is classified as HIGH. You must provision dedicated cloud infrastructure or an isolated VM. Do not run this directly on your local workstation.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-09T13:29:59.260Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-hughpyle-keep/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-09T08:19:07.107Z","emptyReason":null},"readme":"Skill: Reflective Memory\n\nOwner: hughpyle\n\nSummary: Reflective Memory\n\nTags: latest:0.109.0, v0.8.1:0.8.1\n\nVersion history:\n\nv0.109.0 | 2026-03-24T11:19:23.501Z | auto\n\nMajor update with expanded API, flow-based operations, and enhanced documentation.\n\n- Introduces new flow-based API (`keep_flow`, `keep_prompt`, `keep_help`) with standardized parameters for all operations.\n- Protocol Block now uses flow and prompt tool calls instead of direct CLI commands; protocol integrated as a workspace-local file.\n- Adds support for linking provenance of notes and documents using `informs` / `informed_by` tags.\n- Documented tools, parameters, and search steering mechanisms including temporal filtering and relevance bias.\n- Extensive new documentation and CLI/flow usage references; onboarding and guidance materials significantly updated.\n- System integration models updated (MCP, CLI parity, OpenClaw, Claude Code, Kiro, Codex compatibility).\n\nv0.43.5 | 2026-02-16T12:49:13.290Z | auto\n\n- Added hosted-service support: you can now use keepnotes.ai by setting the `KEEPNOTES_API_KEY` (local provider setup is now optional).\n- Expanded system and documentation with additional speech-act status tags (e.g., blocked, declined, fulfilled, open, renegotiated, withdrawn).\n- Introduced new speech-act type tags (assertion, assessment, commitment, declaration, offer, request) for improved tagging and reflection workflows.\n- Added security workflow and dependabot configuration for improved maintenance.\n- Documentation updates: clearer quickstart/setup instructions and new guides (e.g., `KEEP-ANALYZE.md`).\n\nv0.38.4 | 2026-02-13T17:16:02.104Z | auto\n\n- Added support for moving \"now\" history with the new `keep move` command, allowing archiving and topic-based extraction of intention strings.\n- Introduced system-level metadata for albums, artists, and genres.\n- Added new backend, protocol, and remote modules to enhance architecture and future provider integrations.\n- Expanded test coverage with new tests for concurrency, media types, meta resolution, migrations, and recovery.\n- Documentation improvements: new guides for move operations (`KEEP-MOVE.md`), configuration, and architecture.\n- Various enhancements, refactors, and bugfixes across core modules and documentation.\n\nv0.31.0 | 2026-02-11T21:10:54.003Z | auto\n\nVersion 0.31.0 introduces extensive documentation improvements and enhanced reference material.\n\n- Added comprehensive documentation files covering configuration, commands, output, tagging, and versioning.\n- Expanded and updated guides for core commands and APIs: see docs/ for KEEP-CONFIG, KEEP-FIND, KEEP-GET, KEEP-LIST, KEEP-NOW, KEEP-PUT, OUTPUT, TAGGING, and VERSIONING.\n- Updated existing docs (README.md, AGENT-GUIDE.md, PYTHON-API.md, REFERENCE.md) for clarity and completeness.\n- Multiple code files changed for alignment with new documentation and reference standards.\n- Internal improvements to support new documentation structure.\n\nv0.30.2 | 2026-02-11T18:29:57.037Z | auto\n\n**Summary:** This release features major documentation updates, internal reorganization, and test cleanup.\n\n- Documentation overhauled: clearer instructions, quickstart improvements, more precise guidance for tool integrations and first-time setup\n- SKILL.md rewritten: expanded explanations, condensed protocol block, improved clarity on practice and reference commands\n- File organization changed: OpenClaw plugin files moved under keep/data/openclaw-plugin/\n- Tests cleaned up: outdated or redundant tests removed, new test_review_fixes.py added\n- Minor code and config tweaks in alignment with updated docs and restructured content\n\nv0.27.1 | 2026-02-09T02:40:35.808Z | auto\n\n- Added detailed guidance on installing and integrating the keep Protocol Block for persistent reflective practice across projects and agent frameworks.\n- Described OpenClaw plugin and cron-based daily reflection integration for automated context injection and deep self-review.\n- Expanded explanation of the reflective memory practice, including the philosophy behind reflection, conversation types, and value of breakdowns.\n- Provided clearer instructions for first-time setup, document indexing, and environmental variable configuration.\n- Reorganized structure for easier navigation and practical adoption of reflection in daily work.\n\nv0.20.0 | 2026-02-07T17:48:21.604Z | auto\n\n**Summary:** Major update with deeper reflection practices, streamlined protocol, enhanced documentation, and new infrastructure.\n\n- Overhauled SKILL.md to clarify and condense the core reflective protocol and practice.\n- Added guided reflection flow: `keep reflect` now supports structured reflection sessions.\n- Expanded documentation: new guides (releasing, quickstart, architecture, integrations).\n- Automatic installation of protocol block and session hooks for supported tools.\n- Enhanced configuration, tagging, and domain organization strategies.\n- Significant internal changes: added new modules, updated test suite, improved integration structure.\n\nv0.8.1 | 2026-02-04T02:51:30.721Z | auto\n\n**Major update with enhanced self-presence, system document integration, and workflow improvements:**\n\n- Introduced Layer 0: self-installing protocol block and global presence instructions for continued reflective practice across sessions and agents.\n- Replaced embedded pattern documents with internal system docs (`_system:conversations`, `_system:domains`) and moved library content into dedicated `docs/library/`.\n- Improved flow and clarity in the practice guide; updated example commands to use new CLI features (`keep now`, `keep get ... --similar`, etc.).\n- Added persistent version history and context tracking commands; clarified discovery via similar items.\n- Updated install instructions, metadata, and quickstart to match new package structure and local model support.\n- Removed obsolete patterns, test fixtures, and replaced references with new internal resources.\n\nv0.1.0 | 2026-01-31T18:50:06.128Z | auto\n\nInitial public release.\n\n- Introduces “keep” as an associative memory tool for reflection and skillful action.\n- Provides practical guidance for reflective practice before, during, and after actions using CLI commands.\n- Outlines knowledge organization via tagging, summaries, and hierarchical navigation for memory recall.\n- Includes foundational patterns and teachings to bootstrap users’ personal knowledge bases.\n- Features command reference for storing, finding, updating, querying, and recalling information efficiently.\n\nArchive index:\n\nArchive v0.109.0: 319 files, 2876294 bytes\n\nFiles: bench/locomo/ingest.py (10387b), bench/locomo/judge_binary.py (6524b), bench/locomo/llm.py (1844b), bench/locomo/prep_dataset.py (16820b), bench/locomo/query.py (6644b), bench/locomo/README.md (5999b), bench/locomo/results-20260228/judged.json (5319052b), bench/locomo/results-20260228/predictions.json (6792107b), bench/locomo/results-20260228/summary.json (564b), bench/locomo/simulate_continue_trace.py (9827b), claude-code-plugin/hooks/hooks.json (1500b), claude-code-plugin/skills/keep/SKILL.md (2130b), CLAUDE.md (1334b), CONTRIBUTING.md (2747b), docs/AGENT-GUIDE.md (6264b), docs/ANALYSIS.md (5320b), docs/API-SCHEMA.md (14844b), docs/ARCHITECTURE.md (19520b), docs/CLAUDE-DESKTOP.md (598b), docs/design/BUILTIN-STATE-DOCS.md (9288b), docs/design/context-engine.md (9848b), docs/design/email-threading.md (3679b), docs/design/FLOW-CONVERGENCE.md (2884b), docs/design/STATE-ACTIONS.md (22671b), docs/design/STATE-DOC-COMPOSITION.md (3948b), docs/design/STATE-DOC-EXAMPLES.md (9410b), docs/design/STATE-DOC-INTERACTION.md (16349b), docs/design/STATE-DOC-SCHEMA.md (16023b), docs/design/WATCHES.md (4866b), docs/EDGE-TAGS.md (6846b), docs/FLOW_STATE_DOCS.md (8137b), docs/FLOW-ACTIONS.md (13062b), docs/FLOWS.md (10189b), docs/INDEX.md (11110b), docs/KEEP-ANALYZE.md (6481b), docs/KEEP-CONFIG.md (13126b), docs/KEEP-DATA.md (3558b), docs/KEEP-EDIT.md (1188b), docs/KEEP-FIND.md (4993b), docs/KEEP-FLOW.md (7893b), docs/KEEP-GET.md (3139b), docs/KEEP-LIST.md (3065b), docs/KEEP-MCP.md (4676b), docs/KEEP-MOVE.md (4317b), docs/KEEP-NOW.md (3479b), docs/KEEP-PROMPT.md (4844b), docs/KEEP-PUT.md (8476b), docs/LANGCHAIN-INTEGRATION.md (4601b), docs/library/an5.57_translation-en-sujato.json (7443b), docs/library/fortytwo_chapters.txt (33053b), docs/library/han_verse.txt (3689b), docs/library/INDEX.md (7189b), docs/library/mn61.html (25229b), docs/library/mumford_sticks_and_stones.txt (264881b), docs/library/true_person_no_rank.md (7091b), docs/META-TAGS.md (7545b), docs/OPENCLAW-INTEGRATION.md (12777b), docs/OUTPUT.md (8756b), docs/PROMPTS.md (4493b), docs/PYTHON-API.md (11679b), docs/QUICKSTART.md (9783b), docs/REFERENCE.md (8806b), docs/RELEASING.md (1458b), docs/SYSTEM-TAGS.md (4976b), docs/TAGGING.md (11827b), docs/VERSIONING.md (3828b), hatch_build.py (2509b), keep/__init__.py (1884b), keep/__main__.py (102b), keep/_background_processing.py (46801b), keep/_context_resolution.py (34610b), keep/_provider_lifecycle.py (12268b), keep/_search_augmentation.py (30240b), keep/actions/__init__.py (5502b), keep/actions/_item_scope.py (3497b), keep/actions/_tagging.py (3572b), keep/actions/analyze.py (3827b), keep/actions/auto_tag.py (3103b), keep/actions/delete.py (502b), keep/actions/describe.py (2839b)\n\nFile v0.109.0:claude-code-plugin/skills/keep/SKILL.md\n\n---\nname: keep\ndescription: >\n  Reflective Memory. Use when working with memory, reflection, context management,\n  or intent tracking. Provides the reflective memory practice — how and when to use\n  keep tools for capturing insights, tracking commitments, and maintaining awareness.\n---\n\n## keep: Reflective Memory\n\n*Your actions have consequences. Context is fleeting. Pay attention to what is being asked.*\n\n**The practice is `keep_prompt(name=\"reflect\")`.** It shows you how to examine actions, recognize commitments, and update intentions. Run it. Follow the steps. Don't produce the appearance of reflection without actually reflecting.\n\n**Three tools:** `keep_flow` (all operations), `keep_help` (documentation), `keep_prompt` (practice prompts).\n\n```\nkeep_prompt(name=\"reflect\")                                                               # The practice\nkeep_flow(state=\"get-context\", params={item_id: \"now\"}, token_budget=2000)                # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"topic\"}, token_budget=2000)              # What do I know?\nkeep_flow(state=\"put\", params={content: \"what's true now\", id: \"now\"})                    # Update intentions\nkeep_flow(state=\"put\", params={content: \"learning\", tags: {type: \"learning\"}})            # Capture insight\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"X\"}})   # Index a document\nkeep_flow(state=\"tag\", params={id: \"item\", tags: {reviewed: \"true\"}})                     # Tag an item\nkeep_help(topic=\"flow-actions\")                                                            # Action reference\n```\n\n**No MCP?** Every flow has a CLI equivalent: `keep flow get-context -p item_id=now`, `keep flow query-resolve -p query=X`, `keep flow put -p content=X`. Use Bash to run them.\n\n**Protocol:** Reflect using `keep` tools — before, during, and after action. Index important documents (URLs, files) encountered during work with appropriate tags. When writing a plan, incorporate this practice into the plan itself. If the practice is unclear, use `keep_help(topic=\"index\")` to explore the documentation.\n\nFile v0.109.0:SKILL.md\n\n---\nname: keep\nversion: 0.109.0\ndescription: Reflective Memory\nhomepage: https://github.com/keepnotes-ai/keep\nruntime: python:3.12-slim\nuser-invocable: true\nmetadata: {\"openclaw\":{\"emoji\":\"🪞\",\"requires\":{\"bins\":[\"uv\"],\"anyBins\":[\"python\",\"python3\"]},\"install\":[{\"id\":\"uv\",\"kind\":\"uv\",\"package\":\"keep-skill[local]\",\"bins\":[\"keep\"],\"label\":\"Install keep with local models\"}]}}\n---\n\n# Reflective Memory\n\n*A mirror for reflection. A practice for skillful action.*\n\n---\n\nThis skill is offered as a practice, not a specification. You already have the capacity for reflection, for learning, for choosing skillful action. What follows is guidance, pointing at what you can become.\n\n**To get started** follow all the initialization steps below.  Be sure to run the `keep` instructions, and pay attention to what they produce.  This is the first training!\n\n---\n\n## Layer 0: Establishing Presence\n\nThe practice must survive across sessions. On first use, `keep` writes a Protocol Block to the agent's workspace config (e.g. `AGENTS.md` for Claude Code, `codex-setup.md` for Codex). This is a workspace-local file, not a global system modification. The block is versioned and upgraded automatically.\n\n**Self-healing:** If the Protocol Block is missing from your workspace config, restore it. Look for `## keep: Reflective Memory`. If absent, append the block below.\n\n**Protocol Block:**\n\n```markdown\n## keep: Reflective Memory\n\n*Your actions have consequences. Context is fleeting. Pay attention to what is being asked.*\n\n**The practice is `keep_prompt(name=\"reflect\")`.** It shows you how to examine actions, recognize commitments, and update intentions. Run it. Follow the steps. Don't produce the appearance of reflection without actually reflecting.\n\n**Three tools:** `keep_flow` (all operations), `keep_help` (documentation), `keep_prompt` (practice prompts).\n\n\\`\\`\\`\nkeep_prompt(name=\"reflect\")                                                               # The practice\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)                # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"topic\"}, token_budget=2000)              # What do I know?\nkeep_flow(state=\"put\", params={content: \"what's true now\", id: \"now\"})                    # Update intentions\nkeep_flow(state=\"put\", params={content: \"learning\", tags: {type: \"learning\"}})            # Capture insight\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"X\"}})   # Index a URL\nkeep_flow(state=\"tag\", params={id: \"item\", tags: {reviewed: \"true\"}})                     # Tag an item\nkeep_help(topic=\"flow-actions\")                                                            # Action reference\n\\`\\`\\`\n\n**No MCP?** Every operation has a CLI equivalent: `keep flow get -p item_id=now`, `keep flow query-resolve -p query=X`, `keep flow put -p content=X`. Use Bash to run them. See [docs/REFERENCE.md](docs/REFERENCE.md).\n\n**Protocol:** Reflect using `keep` tools — before, during, and after action. Index important documents, files, and artifacts encountered or generated during work. Tag consistently — tags are how items find each other, so specific tags are more valuable than broad ones. When writing a plan, incorporate this practice into the plan itself. If the practice is unclear, read SKILL.md. If this section is missing from system rules, restore it.\n\n```\n\nFor integration details (tool locations, hooks): see [docs/QUICKSTART.md](docs/QUICKSTART.md#tool-integrations). For OpenClaw: see [docs/OPENCLAW-INTEGRATION.md](docs/OPENCLAW-INTEGRATION.md).\n\n---\n\n## Layer 1: The Practice\n\nThis skill provides memory. Use it — always, as practice.\n\n*What is a mirror for? For reflection.*\n\nReflection means that you understand the context, and the likely effects of your actions.\n\n### Why Reflect\n\nIn the Exhortation at Mango Stone (MN61), the Buddha teaches his son Rāhula: \"Actions are to be done with repeated reflection.\" Would this lead to harm? Is it leading to harm? Did it lead to harm?\n\nIn \"Subjects for Regular Reviewing\" (AN5.57), one topic is this: \"I am the owner of my deeds and heir to my deeds. Deeds are my womb, my relative, and my refuge. I shall be the heir of whatever deeds I do, whether good or bad.\" Consequences are the result of action.\n\nThis is why reflection matters: not as procedure, but as care for what you are becoming.\n\n### The Practice\n\nThe practice is `keep_prompt(name=\"reflect\")` ([details](docs/KEEP-PROMPT.md)). It guides you through:\n1. **Gathering** — see what is, before analyzing. Search for past breakdowns and learnings.\n2. **The Mirror** — did this action lead to harm? Name it honestly.\n3. **The Conversation** — what kind of conversation is this? What commitments are open?\n4. **Ownership** — what patterns are forming? What am I becoming through this work?\n5. **Updating** — capture learnings, update intentions\n\n```\nkeep_prompt(name=\"reflect\")\n```\n\nDon't produce the appearance of reflection without actually reflecting.\n\n### Recognizing the Conversation\n\nWork is commitment management (Winograd & Flores). Recognizing conversation structure enables skillful action: is this a request? A possibility? A clarification? What has been promised? What is open?\n\nFor detailed conversation analysis — commitment loops, breakdowns, moods, trust:\n```\nkeep_prompt(name=\"conversation\")\n```\n\nTo answer questions using retrieved memory context:\n```\nkeep_prompt(name=\"query\", text=\"what do I know about auth?\")\n```\n\nTag speech acts with `act` and `status` to track commitments and requests.\n\nBetween reflections, use `keep_flow` to maintain awareness:\n```\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)           # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"this situation\"}, token_budget=2000) # What do I already know?\nkeep_flow(state=\"put\", params={content: \"what happened\", tags: {type: \"learning\"}})  # Capture insight\nkeep_flow(state=\"put\", params={content: \"Assumed X, actually Y\", tags: {type: \"breakdown\"}})  # Index breakdowns\n```\n\n**Index important documents.** Whenever you encounter documents (URLs, files, references) important to the user or task, index them:\n```\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"auth\", project: \"myapp\"}})\nkeep_flow(state=\"put\", params={content: \"file:///path/to/important.pdf\", tags: {type: \"reference\", topic: \"security\"}})\n```\nAsk: What is this document? Why is it important? Tag appropriately. Documents indexed during work become navigable knowledge.\n\n**Link sources to outcomes.** When a document informs a decision or learning, connect them with `informs`/`informed_by`:\n```\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"auth\", informs: \"auth-decision\"}})\nkeep_flow(state=\"put\", params={content: \"We chose OAuth2 because...\", tags: {type: \"learning\", informed_by: \"https://example.com/doc\"}})\n```\nThis makes provenance navigable — `get` on a note shows what informed it, and vice versa.\n\n**Move when pivoting.** When a string of work is complete, or the conversation shifts topic, move the now history before moving on:\n```\nkeep_flow(state=\"move\", params={name: \"auth-string\", tags: {project: \"myapp\"}})  # Archive matching versions\nkeep_flow(state=\"move\", params={name: \"design-log\", only_current: true})         # Move just the tip version\n```\nMoving clears matched versions from now, making room for what's next. Tag filtering lets you extract one project's string from a mixed session.\n\n**Steering search.** Use `bias` to suppress noisy results and boost relevant ones. Use `since`/`until` for temporal filtering:\n```\nkeep_flow(state=\"query-resolve\", params={query: \"auth\", bias: {now: 0}, since: \"P7D\"}, token_budget=1500)\n```\n\n> **No MCP?** Every flow has a CLI equivalent: `keep flow put -p content=X -p tags='{\"k\":\"v\"}'`. See [docs/REFERENCE.md](docs/REFERENCE.md).\n\n**Breakdowns are valuable.** When the normal flow is interrupted — an assumption has been revealed. The breakdown is where learning happens.\n\n* When in conversation, use this practice. Reflect before, during and after action.\n* When writing a plan, make sure the plan incorporates this practice.\n\n## Layer 2: First Time Setup\n\nThe store auto-initializes on first use. For provider configuration, see [docs/QUICKSTART.md](docs/QUICKSTART.md). Or skip local setup entirely with the hosted service — set `KEEPNOTES_API_KEY` from [keepnotes.ai](https://keepnotes.ai).\n\nNow *store and read* the foundational teachings. These are seed wisdom, not test fixtures.\n\n**The Language-Action framework** — conversation types, commitment structure, breakdowns:\n```\nkeep_flow(state=\"get\", params={item_id: \".conversations\"}, token_budget=2000)\n```\n\nUse standard tags for speech acts and status:\n```\nkeep_flow(state=\"get\", params={item_id: \".tag/act\"}, token_budget=1000)      # Speech-act categories\nkeep_flow(state=\"get\", params={item_id: \".tag/status\"}, token_budget=1000)   # Lifecycle status\n```\n\n**The mirror teaching** (MN61) — actions reflected upon before, during, after:\n```\nkeep_flow(state=\"put\", params={content: \"file://SKILL_DIR/docs/library/mn61.html\", tags: {type: \"teaching\", topic: \"reflection\"}})\nkeep_flow(state=\"get\", params={item_id: \"file://SKILL_DIR/docs/library/mn61.html\"}, token_budget=2000)\n```\n> Use `keep config tool` in the terminal to find SKILL_DIR, or use the path from your skill installation.\n\n**Ownership of deeds** (AN5.57) — \"I am the owner of my deeds and heir to my deeds.\":\n```\nkeep_flow(state=\"put\", params={content: \"file://SKILL_DIR/docs/library/an5.57_translation-en-sujato.json\", tags: {type: \"teaching\", topic: \"action\"}})\nkeep_flow(state=\"get\", params={item_id: \"file://SKILL_DIR/docs/library/an5.57_translation-en-sujato.json\"}, token_budget=2000)\n```\n\n**The han verse** — Awake! _aquí donde las papas queman_, \"慎勿放逸\":\n```\nkeep_flow(state=\"put\", params={content: \"file://SKILL_DIR/docs/library/han_verse.txt\", tags: {type: \"teaching\", topic: \"urgency\"}})\nkeep_flow(state=\"get\", params={item_id: \"file://SKILL_DIR/docs/library/han_verse.txt\"}, token_budget=2000)\n```\n\n**Now reflect:** What did you learn? Save your understanding:\n```\nkeep_flow(state=\"put\", params={content: \"My understanding of the practice: ...\", tags: {type: \"learning\"}})\n```\n\nFor installation options, see [docs/QUICKSTART.md](docs/QUICKSTART.md).\n\n---\n\n## Layer 3: Quick Reference\n\nAll operations use `keep_flow(state, params, token_budget)`:\n\n```\n# Context\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)        # Current intentions\nkeep_flow(state=\"get\", params={item_id: \"ID\"}, token_budget=2000)         # Item with similar/meta/versions\n\n# Search\nkeep_flow(state=\"query-resolve\", params={query: \"authentication\"}, budget=3, token_budget=2000)\nkeep_flow(state=\"query-resolve\", params={query: \"auth\", tags: {project: \"myapp\"}}, token_budget=2000)\nkeep_flow(state=\"query-resolve\", params={query: \"recent\", since: \"P1D\", bias: {now: 0}}, token_budget=1500)\nkeep_flow(state=\"find-deep\", params={query: \"auth patterns\"}, token_budget=2000)  # With edge traversal\n\n# Write\nkeep_flow(state=\"put\", params={content: \"insight\", tags: {type: \"learning\"}})\nkeep_flow(state=\"put\", params={content: \"Working on auth flow\", id: \"now\"})       # Update intentions\nkeep_flow(state=\"put\", params={content: \"I'll fix auth\", tags: {act: \"commitment\", status: \"open\"}})\n\n# Tag & organize\nkeep_flow(state=\"tag\", params={id: \"ID\", tags: {reviewed: \"true\"}})               # Tag an item\nkeep_flow(state=\"move\", params={name: \"auth-string\", tags: {project: \"myapp\"}})   # Move versions from now\nkeep_flow(state=\"delete\", params={id: \"ID\"})                                      # Remove item\n```\n\n**Domain organization** — tagging strategies, collection structures:\n```\nkeep_flow(state=\"get\", params={item_id: \".domains\"}, token_budget=1000)\n```\n\nUse `project` tags for bounded work, `topic` for cross-cutting knowledge.\nYou can read (and update) descriptions of these tagging taxonomies as you use them.\n\n```\nkeep_flow(state=\"get\", params={item_id: \".tag/project\"}, token_budget=1000)\nkeep_flow(state=\"get\", params={item_id: \".tag/topic\"}, token_budget=1000)\n```\n\nFor CLI reference, see [docs/REFERENCE.md](docs/REFERENCE.md). Per-command details in `docs/KEEP-*.md`.\n\n---\n\n## See Also\n\n- [docs/AGENT-GUIDE.md](docs/AGENT-GUIDE.md) — Detailed patterns for working sessions\n- [docs/REFERENCE.md](docs/REFERENCE.md) — Quick reference index\n- [docs/TAGGING.md](docs/TAGGING.md) — Tags, speech acts, project/topic\n- [docs/QUICKSTART.md](docs/QUICKSTART.md) — Installation and setup\n- [keep/data/system/conversations.md](keep/data/system/conversations.md) — Full conversation framework (`.conversations`)\n- [keep/data/system/domains.md](keep/data/system/domains.md) — Domain-specific organization (`.domains`)\n\nFile v0.109.0:bench/locomo/README.md\n\n# LoCoMo Benchmark for keep\n\nReproduces the [LoCoMo](https://github.com/snap-research/LoCoMo) benchmark for long-term conversational memory using `keep` as the memory backend.\n\n## Results\n\nEvaluated using the standard binary LLM-as-judge methodology (using the `gpt-4o-mini` model),\nconsistent with published results from other memory systems.\nResults are from a single run (not averaged over multiple runs).\n\n| Category | Score | Questions |\n|---|---|---|\n| Single-hop | 86.2% | 841 |\n| Temporal | 68.5% | 321 |\n| Multi-hop | 64.2% | 282 |\n| Open-domain | 50.0% | 96 |\n| **Overall** | **76.2%** | **1540** |\n\n\n### Stack\n\n| Component | Model | Location |\n|---|---|---|\n| Embeddings | nomic-embed-text | Local (Ollama) |\n| Analysis/summarization | llama3.2:3b | Local (Ollama) |\n| Query answering | gpt-4o-mini | OpenAI API |\n| Judge | gpt-4o-mini | OpenAI API |\n\nkeep's embedding and summarization providers (and their prompts) are user-configurable.\nThis benchmark used local Ollama models, but keep also supports OpenAI, Anthropic,\nand other API providers, as well as the [keepnotes.ai](https://keepnotes.ai)\nhosted service.\n\n### Comparison with published results\n\nFor context, here are publicly reported LoCoMo scores from other memory systems,\nsourced from [Memobase](https://github.com/memodb-io/memobase/tree/main/docs/experiments/locomo-benchmark)\nand [MemMachine](https://memmachine.ai/blog/2025/09/memmachine-reaches-new-heights-on-locomo/).\nMethodologies vary across systems (different models, retrieval strategies,\njudge configurations), so these are reference points rather than\nstrict apples-to-apples comparisons.\n\n| System | Single-hop | Temporal | Multi-hop | Open-domain | Overall |\n|---|---|---|---|---|---|\n| MemMachine | 93.3 | 72.6 | 80.5 | 64.6 | 84.9 |\n| **keep** | **86.2** | **68.5** | **64.2** | **50.0** | **76.2** |\n| Memobase v0.0.37 | 70.9 | 85.1 | 46.9 | 77.2 | 75.8 |\n| Zep | 74.1 | 79.8 | 66.0 | 67.7 | 75.1 |\n| Mem0 | 67.1 | 55.5 | 51.2 | 72.9 | 66.9 |\n| LangMem | 62.2 | 23.4 | 47.9 | 71.1 | 58.1 |\n| OpenAI | 63.8 | 21.7 | 42.9 | 62.3 | 52.9 |\n\n## Dataset\n\nDownload `locomo10.json` from [snap-research/LoCoMo](https://github.com/snap-research/LoCoMo/tree/main/data)\nand place it in `dataset/`.\n\nThe dataset contains 10 multi-session conversations between character pairs,\nwith 1,986 QA items across 5 categories:\n\n| Category | Questions | Description |\n|---|---|---|\n| Single-hop | 841 | Factual recall from a single session |\n| Temporal | 321 | Time/date reasoning across sessions |\n| Multi-hop | 282 | Synthesizing facts from multiple sessions |\n| Open-domain | 96 | Integrating conversation context with world knowledge |\n| Adversarial | 446 | Questions about things never discussed (expect refusal) |\n\n**Note on category numbering:** The paper's numbered list (1-5) does not match\nthe category IDs in the dataset JSON. See [MemMachine's Appendix A](https://memmachine.ai/blog/2025/09/memmachine-reaches-new-heights-on-locomo/#appendix-a)\nfor the correct mapping.\n\n## Pipeline\n\n### 1. Prepare dataset\n\n```bash\npython prep_dataset.py --locomo dataset/locomo10.json --out-dir prepared/\n```\n\nParses the raw LoCoMo JSON into structured files for ingestion:\n- `versioned_session_notes.json` — conversation turns grouped by session\n- `image_notes.json` — image descriptions with metadata\n- `qa_dataset.json` — 1,986 QA items with category labels\n\n### 2. Ingest into keep\n\n```bash\npython ingest.py --store stores/run-001 --strategy turns-as-versions --data-dir prepared/\n```\n\nCreates an isolated keep store. The `turns-as-versions` strategy models each\nconversation session as a versioned document (vstring), with individual turns\nas versions. This preserves temporal ordering and enables keep's version-aware\nretrieval.\n\n**Prerequisites:** Ollama running (models are pulled automatically on first use).\n\n### 3. Analyze\n\n```bash\nkeep --store stores/run-001 analyze --all\n```\n\nRuns keep's [analysis pipeline](../../docs/KEEP-ANALYZE.md) (using llama3.2:3b via Ollama)\nto decompose conversations into searchable parts. Analysis extracts structured facts,\nrelationships, and temporal markers that improve retrieval quality.\n\n### 4. Query\n\n```bash\npython query.py --store stores/run-001 --out results-20260228/run-001_predictions.json \\\n    --model gpt-4o-mini --deep\n```\n\nFor each QA item, uses keep's built-in [query prompt template](../../keep/data/system/prompt-agent-query.md) with deep retrieval\n(tag-following across related documents). The `--deep` flag enables cross-document\ncontext assembly with a default 3000-token budget.\n\nSupports `--resume-from N` for crash recovery.\n\n### 5. Judge\n\n```bash\npython judge_binary.py --predictions results-20260228/run-001_predictions.json \\\n    --out results-20260228/run-001_judged.json --model gpt-4o-mini\n```\n\nBinary LLM-as-judge evaluation using the prompt from the\n[Memobase evaluation harness](https://github.com/memodb-io/memobase/blob/main/docs/experiments/locomo-benchmark/metrics/llm_judge.py).\nAdversarial questions are excluded from scoring.\n\nSupports `--resume-from N` for crash recovery.\n\n## Requirements\n\n```\nkeep-skill>=0.74.0\nopenai>=1.0\n```\n\nThese are the defaults used in this benchmark. To use different providers,\nconfigure keep's `embedding` and `summarization` settings (see keep docs).\n\nFor local reproduction, Ollama must be running. Models are pulled automatically\non first use.\n\n## Scoring methodology\n\nThe **LLM Judge Score** uses gpt-4o-mini to compare each prediction against\nthe ground truth answer. The judge is instructed to be generous — as long as\nthe prediction touches on the same topic as the gold answer, it scores 1.\nTime-related answers are scored correct if they refer to the same date/period\nregardless of format.\n\nThe **Overall** score is a weighted average across the four non-adversarial\ncategories (weighted by question count).\n\nThis methodology is consistent with what is used by MemMachine, Memobase, Zep,\nMem0, LangMem, and OpenAI in their published LoCoMo results.\n\nFile v0.109.0:langchain-keep/README.md\n\n# langchain-keep\n\nLangChain integration for [keep](https://github.com/keepnotes-ai/keep) — reflective memory for AI agents.\n\nThis is a convenience package that installs `keep-skill[langchain]` and re-exports the integration components.\n\n## Installation\n\n```bash\npip install langchain-keep\n```\n\n## Usage\n\n```python\nfrom langchain_keep import KeepStore, KeepNotesToolkit, KeepNotesRetriever\n\n# LangGraph BaseStore\nstore = KeepStore()\n\n# LangChain tools\nfrom keep import Keeper\ntoolkit = KeepNotesToolkit(keeper=Keeper())\ntools = toolkit.get_tools()\n\n# RAG retriever\nretriever = KeepNotesRetriever(keeper=Keeper(), k=5)\n```\n\n## What's included\n\n| Component | Description |\n|-----------|-------------|\n| `KeepStore` | LangGraph `BaseStore` backed by Keep |\n| `KeepNotesToolkit` | 4 LangChain tools (remember, recall, get/set context) |\n| `KeepNotesRetriever` | `BaseRetriever` with optional now-context |\n| `KeepNotesMiddleware` | LCEL runnable for auto-injecting memory context |\n\n## Configuration\n\nYou need an embedding provider configured. Simplest:\n\n```bash\nexport OPENAI_API_KEY=...    # or GEMINI_API_KEY\n```\n\nOr use the hosted service:\n\n```bash\nexport KEEPNOTES_API_KEY=... # Sign up at https://keepnotes.ai\n```\n\nSee the [full documentation](https://docs.keepnotes.ai) for all provider options.\n\n## Links\n\n- [Documentation](https://docs.keepnotes.ai)\n- [GitHub](https://github.com/keepnotes-ai/keep)\n- [keep on PyPI](https://pypi.org/project/keep-skill/)\n\nFile v0.109.0:README.md\n\n# keep\n\nAn agent-skill: memory that pays attention.\n\nIt includes [skill instructions](SKILL.md) for reflective practice, and a powerful semantic memory system with [command-line](docs/QUICKSTART.md) and [MCP](docs/KEEP-MCP.md) interfaces. Fully local, or use API keys for model providers, or [cloud-hosted](https://keepnotes.ai) for multi-agent use.\n\n```bash\nuv tool install keep-skill       # or: pip install keep-skill\nexport OPENAI_API_KEY=...        # Or GEMINI_API_KEY (both do embeddings + summarization)\n\n# Index content (store auto-initializes on first use)\nkeep put https://inguz.substack.com/p/keep -t topic=practice\nkeep put \"Rate limit is 100 req/min\" -t topic=api\n\n# Index a codebase — recursive, with daemon-driven watch for changes\nkeep put ./my-project/ -r --watch\n\n# Search by meaning\nkeep find \"what's the rate limit?\"\n\n# Track what you're working on\nkeep now \"Debugging auth flow\"\n\n# Instructions for reflection\nkeep prompt reflect\n```\n\n---\n\n## What It Does\n\nStore anything — notes, files, URLs — and `keep` summarizes, embeds, and tags each item. You search by meaning, not keywords. Content goes in as text, PDF, HTML, Office documents, audio, or images; what comes back is a summary with tags and semantic neighbors. Audio and image files auto-extract metadata tags (artist, album, camera, date, etc.).\n\nWhat makes this more than a vector store: tags become edges. Define a tag like `author` or `git_commit` and keep creates bidirectional links — a user-defined graph model where every tag can be a navigable relationship. When you retrieve any item, keep follows these edges and fires standing queries — surfacing open commitments, past learnings, referenced files, commit history. The right things appear at the right time, without manual graph construction.\n\n- **Summarize, embed, tag** — URLs, files, and text are summarized and indexed on ingest\n- **Contextual feedback** — Open commitments and past learnings surface automatically\n- **Semantic search** — Find by meaning, not keywords; scope to a folder or project\n- **Tag organization** — Speech acts, status, project, topic, type — structured and queryable\n- **Deep search** — Follow edges and tags from results to discover related items across the graph\n- **Edge tags** — Turn tags into navigable relationships with automatic inverse links\n- **Git changelog** — Commits indexed as searchable items with edges to touched files\n- **Parts** — `analyze` decomposes documents into searchable sections, each with its own embedding and tags\n- **Strings** — Every note is a string of versions; reorganize history by meaning with `keep move`\n- **Watches** — Daemon-driven directory and file monitoring; re-indexes on change\n- **Works offline** — Local models (MLX, Ollama), or API providers (Voyage, OpenAI, Gemini, Anthropic, Mistral)\n\nBacked by ChromaDB for vectors, SQLite for metadata and versions.\n\n> **[keepnotes.ai](https://keepnotes.ai)** — Hosted service. No local setup, no API keys to manage. Same SDK, managed infrastructure.\n\n### The Practice\n\nkeep is designed as a skill for AI agents — a practice, not just a tool. The [skill instructions](SKILL.md) teach agents to reflect before, during, and after action: check intentions, recognize commitments, capture learnings, notice breakdowns. `keep prompt reflect` guides a structured reflection ([details](docs/KEEP-PROMPT.md)); `keep now` tracks current intentions and surfaces what's relevant.\n\nThis works because the tool and the skill reinforce each other. The tool stores and retrieves; the skill says *when* and *why*. An agent that uses both develops *skillful action* across sessions — not just recall, but looking before acting, and a deep review of outcomes afterwards.\n\n> Why build memory for AI agents? What does \"reflective practice\" mean here? **[Read our blog for the back-story →](https://keepnotes.ai/blog/)**\n\n### Integration\n\nThe skill instructions and hooks install into your agent's configuration automatically on first use. The CLI alone is enough to start; the hooks make it automatic.\n\n| Tool | Integration |\n|------|-------------|\n| **[OpenClaw](docs/OPENCLAW-INTEGRATION.md)** | Context engine plugin — full memory assembly, session archival, reflection triggers |\n| **Claude Desktop** | `keep config mcpb` ([details](docs/CLAUDE-DESKTOP.md)) |\n| **Claude Code** | Plugin: `/plugin install keep@keepnotes-ai` |\n| **VS Code Copilot** | MCP: `code --add-mcp '{\"name\":\"keep\",\"command\":\"keep\",\"args\":[\"mcp\"]}'` |\n| **Kiro** | MCP + practice prompt: `kiro-cli mcp add --name keep --scope global -- keep mcp` |\n| **OpenAI Codex** | MCP: `codex mcp add keep -- keep mcp` |\n| **LangChain** | [LangGraph BaseStore](docs/LANGCHAIN-INTEGRATION.md), retriever, tools, and middleware |\n| **Any MCP client** | [Stdio server](docs/KEEP-MCP.md) with 3 tools (`keep_flow`, `keep_prompt`, `keep_help`) |\n\nAfter install, just tell your agent: *Please read all the keep_help documentation, and then use keep_prompt(name=\"reflect\") to save some notes about what you learn.*\n\n---\n\n## Installation\n\n**Python 3.11–3.13 required.** Use [uv](https://docs.astral.sh/uv/) (recommended) or pip:\n\n```bash\nuv tool install keep-skill\n```\n\n**Hosted** (simplest — no local setup needed):\n```bash\nexport KEEPNOTES_API_KEY=...   # Sign up at https://keepnotes.ai\n```\n\n**Self-hosted** with API providers:\n```bash\nexport OPENAI_API_KEY=...      # Simplest (handles both embeddings + summarization)\n# Or: GEMINI_API_KEY=...       # Also does both\n# Or: VOYAGE_API_KEY=... and ANTHROPIC_API_KEY=...  # Separate services\n```\n\n**Local** (offline, no API keys): If [Ollama](https://ollama.com/) is running, keep auto-detects it. Or on macOS Apple Silicon: `uv tool install 'keep-skill[local]'`\n\n**LangChain/LangGraph** integration: `pip install keep-skill[langchain]` or `pip install langchain-keep`\n\nSee [docs/QUICKSTART.md](docs/QUICKSTART.md) for all provider options.\n\n---\n\n## Quick Start\n\n```bash\n# Index URLs, files, and notes (store auto-initializes on first use)\nkeep put https://example.com/api-docs -t topic=api\nkeep put \"Token refresh needs clock sync\" -t topic=auth\n\n# Index a codebase — recursive, with auto-watch for changes\nkeep put ./my-project/ -r --watch\n# git: 2 repo(s) queued for changelog ingest\n\n# Search\nkeep find \"authentication flow\" --limit 5\nkeep find \"auth\" --deep                # Follow edges to discover related items\nkeep find \"auth\" --scope 'file:///Users/me/project/*'  # Scoped to a folder\n\n# Retrieve\nkeep get file:///path/to/doc.md\nkeep get ID --history                  # All versions\nkeep get ID --parts                    # Analyzed sections\n\n# Tags\nkeep list --tag project=myapp          # Find by tag\nkeep list 'git://github.com/org/repo@*'  # All git tags/releases\n\n# Current intentions\nkeep now                               # Show what you're working on\nkeep now \"Fixing login bug\"            # Update intentions\n```\n\n### Python API\n\n```python\nfrom keep import Keeper\n\nkp = Keeper()\n\n# Index\nkp.put(uri=\"file:///path/to/doc.md\", tags={\"project\": \"myapp\"})\nkp.put(\"Rate limit is 100 req/min\", tags={\"topic\": \"api\"})\n\n# Search\nresults = kp.find(\"rate limit\", limit=5)\nfor r in results:\n    print(f\"[{r.score:.2f}] {r.summary}\")\n\n# Version history\nprev = kp.get_version(\"doc:1\", offset=1)\nversions = kp.list_versions(\"doc:1\")\n```\n\nSee [docs/QUICKSTART.md](docs/QUICKSTART.md) for configuration and more examples.\n\n---\n\n## Documentation\n\nFull docs at **[docs.keepnotes.ai](https://docs.keepnotes.ai)** — or browse locally:\n\n- **[docs/QUICKSTART.md](docs/QUICKSTART.md)** — Setup, configuration, first steps\n- **[docs/REFERENCE.md](docs/REFERENCE.md)** — Quick reference index\n- **[docs/KEEP-PUT.md](docs/KEEP-PUT.md)** — Indexing: files, directories, URLs, git changelog, watches\n- **[docs/KEEP-FIND.md](docs/KEEP-FIND.md)** — Semantic search, deep search, scoped search\n- **[docs/TAGGING.md](docs/TAGGING.md)** — Tags, speech acts, project/topic organization\n- **[docs/PROMPTS.md](docs/PROMPTS.md)** — Prompts for summarization, analysis, and agent workflows\n- **[docs/OPENCLAW-INTEGRATION.md](docs/OPENCLAW-INTEGRATION.md)** — OpenClaw context engine plugin\n- **[docs/KEEP-MCP.md](docs/KEEP-MCP.md)** — MCP server for AI agent integration\n- **[docs/AGENT-GUIDE.md](docs/AGENT-GUIDE.md)** — Working session patterns\n- **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** — How it works under the hood\n- **[SKILL.md](SKILL.md)** — The reflective practice (for AI agents)\n\n---\n\n## License\n\nMIT\n\n---\n\n## Contributing\n\nPublished on [PyPI as `keep-skill`](https://pypi.org/project/keep-skill/).\n\nIssues and PRs welcome:\n- Provider implementations\n- Performance improvements\n- Documentation clarity\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\nFile v0.109.0:_meta.json\n\n{\n  \"ownerId\": \"kn72wa47ddf3nr5g4kv7xgt27s8092gt\",\n  \"slug\": \"keep\",\n  \"version\": \"0.109.0\",\n  \"publishedAt\": 1774351163501\n}\n\nFile v0.109.0:CLAUDE.md\n\n# keep — Reflective Memory for AI Agents\n\n## MANDATORY: This is a PUBLIC repository\n\nThis repository is open-source and public on GitHub. Every commit is visible to the world.\n\n**NEVER commit or include:**\n- API keys, tokens, secrets, credentials, or .env files\n- Business plans, financial data, pricing, or revenue information\n- Customer data, user information, or private communications\n- Internal infrastructure details (IPs, DSNs, deployment configs)\n- Content from any private repository or internal systems\n\nIf you accidentally stage private content, stop and alert the user before committing.\n\n## Repository structure\n\n- `keep/` — core library (keep-skill on PyPI)\n- `langchain-keep/` — LangChain integration (langchain-keep on PyPI)\n- `tests/` — test suite (run with `python -m pytest tests/`)\n- `scripts/bump_version.py` — version management\n\n## Release process\n\n1. `python scripts/bump_version.py X.Y.Z`\n2. Commit, tag `vX.Y.Z`, push with `--tags`\n3. `python -m build && twine upload dist/keep_skill-X.Y.Z*`\n4. `gh release create vX.Y.Z`\n\nBoth `keep-skill` and `langchain-keep` go to PyPI.\n\n## Testing\n\n```bash\npython -m pytest tests/ -x -q    # full suite (~500 tests, ~90s)\npython -m pytest tests/test_deferred_embedding.py -v  # specific file\n```\n\nUses `mock_providers` fixture to avoid loading real ML models.\n\nFile v0.109.0:CONTRIBUTING.md\n\n# Contributing to keep-skill\n\nThis project is published on [PyPI as `keep-skill`](https://pypi.org/project/keep-skill/). Contributions are welcome under the MIT license.\n\n## How to Contribute\n\n- **Found a bug or have a feature idea?** Open an issue on GitHub\n- **Want to fix something?** Check the open issues, or submit a fix directly\n- **Making changes:** Fork the repo, create a feature branch, and open a pull request against `main`\n\nAll contributions appreciated!\n\n## Versioning\n\nWe use [semantic versioning](https://semver.org/):\n\n- **MAJOR** (1.0.0 → 2.0.0): Breaking changes to the public API\n- **MINOR** (0.1.0 → 0.2.0): New features, backward compatible\n- **PATCH** (0.1.0 → 0.1.1): Bug fixes, backward compatible\n\n**Current status:** Pre-1.0 (0.x.y), so minor versions may include breaking changes, but we try to avoid them.\n\nVersion is defined in `pyproject.toml` (single source of truth). Run the bump script to update all locations:\n```bash\npython scripts/bump_version.py x.y.z\n```\n\nThe `langchain-keep` shim package (`langchain-keep/pyproject.toml`) has its own version and pins `keep-skill[langchain]>=` to the minimum compatible release.\n\n## Public API\n\nThe following are considered public API — changes require version bumps and deprecation consideration:\n\n**Python API:**\n- `Keeper` class and its public methods\n- `Item` type and its fields\n- Anything exported in `keep/__init__.py`\n- `keep.langchain` module: `KeepStore`, `KeepNotesToolkit`, `KeepNotesRetriever`, `KeepNotesMiddleware`\n\n**CLI:**\n- All commands (`keep find`, `keep put`, `keep get`, etc.)\n- Command-line argument names and behavior\n\n**Not public API** (can change without notice):\n- Internal modules (`store.py`, `chunking.py`, `indexing.py`, etc.)\n- Provider implementations\n- Configuration file format (may evolve)\n\n## Backward Compatibility Guidelines\n\nWhen making changes:\n\n1. **Don't remove or rename public methods** — deprecate first, remove in next major version\n2. **Don't change method signatures** — add new optional parameters with defaults\n3. **Don't change return types** — extend, don't replace\n4. **CLI changes** — keep old flags working, add new ones\n\nIf you must break compatibility:\n- Document in commit message and changelog\n- Bump version appropriately\n- Provide migration guidance\n\n## Releases\n\nReleases are managed by the maintainer. To prepare a release:\n\n```bash\n# 1. Bump version\npython scripts/bump_version.py x.y.z\n\n# 2. Commit\ngit add -A && git commit -m \"Release x.y.z\"\ngit tag vx.y.z\ngit push origin main --tags\n\n# 3. Build and publish (from machine with PyPI credentials)\nrm -rf dist/ build/\npython -m build\ntwine check dist/*\ntwine upload dist/*\n```\n\n## Questions?\n\nOpen an issue or reach out to the maintainer.\n\nFile v0.109.0:docs/AGENT-GUIDE.md\n\n# Reflective Memory — Agent Guide\n\nPatterns for using the reflective memory store effectively in working sessions.\n\nFor the practice (why and when), see [../SKILL.md](../SKILL.md).\nFor CLI reference, see [REFERENCE.md](REFERENCE.md). For the output format, see [OUTPUT.md](OUTPUT.md).\n\n> **Note:** Examples below use `keep_flow` (the primary MCP interface). CLI equivalents (`keep flow put -p content=X`, etc.) are available for hooks and terminal use — see [REFERENCE.md](REFERENCE.md).\n\n---\n\n## The Practice\n\nThis guide assumes familiarity with the reflective practice in [SKILL.md](../SKILL.md). The key points:\n\n**Reflect before acting:** Check your current work context and intentions.\n- What kind of conversation is this? (Action? Possibility? Clarification?)\n- What do I already know?\n```\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)\nkeep_flow(state=\"query-resolve\", params={query: \"this situation\"}, token_budget=2000)\n```\n\n**While acting:** Is this leading to harm? If yes: give it up.\n\n**Reflect after acting:** What happened? What did I learn?\n```\nkeep_flow(state=\"put\", params={content: \"what I learned\", tags: {type: \"learning\"}})\n```\n\n**Periodically:** Run a full structured reflection ([details](KEEP-PROMPT.md)):\n```\nkeep_prompt(name=\"reflect\")\n```\n\nThis cycle — reflect, act, reflect — is the mirror teaching. Memory isn't storage; it's how you develop skillful judgment.\n\n---\n\n## Working Session Pattern\n\nUse the nowdoc as a scratchpad to track where you are in the work. This isn't enforced structure — it's a convention that helps you (and future agents) maintain perspective.\n\n```\n# 1. Starting work — check context and intentions\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)\n\n# 2. Update context as work evolves\nkeep_flow(state=\"put\", params={content: \"Diagnosing flaky test in auth module\", id: \"now\", tags: {project: \"myapp\", topic: \"testing\"}})\nkeep_flow(state=\"put\", params={content: \"Found timing issue\", id: \"now\", tags: {project: \"myapp\"}})\n\n# 3. Record learnings\nkeep_flow(state=\"put\", params={content: \"Flaky timing fix: mock time instead of real assertions\", tags: {topic: \"testing\", type: \"learning\"}})\n```\n\n**Key insight:** The store remembers across sessions; working memory doesn't. When you resume, read context first. All updates create version history automatically.\n\n---\n\n## Agent Handoff\n\n**Starting a session:**\n```\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)\nkeep_flow(state=\"query-resolve\", params={query: \"recent work\", since: \"P1D\"}, token_budget=1500)\n```\n\n**Ending a session:**\n```\nkeep_flow(state=\"put\", params={content: \"Completed OAuth2 flow. Token refresh working. Next: add tests.\", id: \"now\", tags: {topic: \"auth\"}})\nkeep_flow(state=\"move\", params={name: \"auth-string\", tags: {project: \"myapp\"}})\n```\n\n---\n\n## Strings\n\nAs you work, `now` accumulates a string of versions — a trace of how intentions evolved. The `move` flow lets you name and archive that string, making room for what's next.\n\n**Snapshot before pivoting.** When the conversation shifts topic:\n```\nkeep_flow(state=\"move\", params={name: \"auth-string\", tags: {project: \"myapp\"}})\nkeep_flow(state=\"put\", params={content: \"Starting on database migration\", id: \"now\"})\n```\n\n**Incremental archival.** Move to the same name repeatedly — versions append:\n```\nkeep_flow(state=\"move\", params={name: \"design-log\", tags: {project: \"myapp\"}})\n```\n\n**Tag-filtered extraction.** When a session mixes projects:\n```\nkeep_flow(state=\"move\", params={name: \"frontend-work\", tags: {project: \"frontend\"}})\n```\n\n---\n\n## Index Important Documents\n\nWhenever you encounter documents important to the task, index them:\n\n```\nkeep_flow(state=\"put\", params={content: \"https://docs.example.com/auth\", tags: {topic: \"auth\", project: \"myapp\"}})\nkeep_flow(state=\"put\", params={content: \"file:///path/to/design.pdf\", tags: {type: \"reference\", topic: \"architecture\"}})\n```\n\nAsk: what is this? Why is it important? Tag appropriately.\n\n---\n\n## Breakdowns as Learning\n\nWhen the normal flow is interrupted — an assumption has been revealed. **First:** complete the immediate conversation. **Then record:**\n\n```\nkeep_flow(state=\"put\", params={content: \"Assumed user wanted full rewrite. Actually: minimal patch.\", tags: {type: \"breakdown\"}})\n```\n\nBreakdowns are how agents learn.\n\n---\n\n## Tracking Commitments\n\nUse speech-act tags to make the commitment structure visible:\n\n```\n# Track promises\nkeep_flow(state=\"put\", params={content: \"I'll fix the auth bug\", tags: {act: \"commitment\", status: \"open\", project: \"myapp\"}})\n\n# Track requests\nkeep_flow(state=\"put\", params={content: \"Please review the PR\", tags: {act: \"request\", status: \"open\"}})\n\n# Query open work\nkeep_flow(state=\"query-resolve\", params={query: \"open commitments\", tags: {act: \"commitment\", status: \"open\"}}, token_budget=1000)\n\n# Close the loop\nkeep_flow(state=\"tag\", params={id: \"ID\", tags: {status: \"fulfilled\"}})\n```\n\nSee [TAGGING.md](use keep_help with topic=\"tagging\") for the full speech-act framework.\n\n---\n\n## Data Model\n\nAn item has:\n- A unique identifier (URI, content hash, or system ID)\n- Timestamps (`_created`, `_updated`)\n- A summary of the content\n- Tags (`{key: value, ...}`)\n- Version history (previous versions archived automatically)\n\nThe full original document is not stored. Summaries are contextual — tags shape how new items are understood. See [KEEP-PUT.md](use keep_help with topic=\"keep-put\").\n\n---\n\n## System Documents\n\nBundled system docs provide patterns and conventions, accessible via `get`:\n\n| ID | What it provides |\n|----|------------------|\n| `.domains` | Domain-specific organization patterns |\n| `.conversations` | Conversation framework (action, possibility, clarification) |\n| `.tag/act` | Speech-act categories |\n| `.tag/status` | Lifecycle states |\n| `.tag/project` | Project tag conventions |\n| `.tag/topic` | Topic tag conventions |\n\n---\n\n## See Also\n\n- [FLOW-ACTIONS.md](use keep_help with topic=\"flow-actions\") — Action reference\n- [KEEP-FLOW.md](use keep_help with topic=\"keep-flow\") — Running and steering flows\n- [REFERENCE.md](use keep_help with topic=\"reference\") — CLI quick reference\n- [TAGGING.md](use keep_help with topic=\"tagging\") — Tags, speech acts, project/topic\n\nFile v0.109.0:docs/ANALYSIS.md\n\n# Document Analysis\n\nAnalysis decomposes documents into meaningful parts — themes, episodes, commitments — each with its own summary and embedding. This makes your store searchable at a finer grain than whole documents.\n\n## The problem with whole-document search\n\nSemantic search matches your query against document summaries. This works well for focused notes, but struggles with long or multi-topic content:\n\n- A meeting transcript covers auth, pricing, and deployment. Searching for \"authentication\" matches weakly because the summary mentions all three topics equally.\n- A working session (`now`) accumulates days of context across several projects. Searching for one project returns the whole session with a mediocre similarity score.\n- A PDF has 20 pages. The summary captures the gist but loses the specific argument on page 12.\n\nThe summary is a lossy compression. Analysis recovers what was lost.\n\n## What analysis produces\n\n`keep analyze` breaks content into **parts** — each a coherent unit of meaning with its own summary, tags, and embedding vector:\n\n```\nDocument: \"Meeting notes 2026-02-18\"\n  @P{1}  Authentication: team agreed on OAuth2 + PKCE for the mobile app\n  @P{2}  Pricing: decided to keep free tier at 1000 requests/day\n  @P{3}  Deployment: migrating to us-east-1 by end of month\n```\n\nNow searching for \"authentication\" matches `@P{1}` directly — high similarity, precise result. The other parts match their own topics independently.\n\n## Two decomposition modes\n\nAnalysis auto-detects the content type:\n\n**Structural decomposition** (documents, URIs): Splits by headings, topic shifts, and natural section boundaries. A PDF becomes chapters. An article becomes arguments. A spec becomes requirements.\n\n**Episodic decomposition** (strings with version history): Assembles the full version history chronologically and splits by time, topic shifts, or narrative arcs. A working session becomes project episodes. A learning journal becomes distinct insights.\n\nBoth modes also extract:\n- **Commitments**: promises, requests, declarations, and their status (open, fulfilled, withdrawn)\n- **User facts**: concrete details stated by the user (dates, names, decisions)\n\n## How parts improve search\n\nParts participate in search alongside regular documents. When you `keep find`, results may include both whole documents and individual parts:\n\n```bash\nkeep find \"OAuth2 mobile authentication\"\n# %a1b2c3d4@P{1}   2026-02-18  Authentication: team agreed on OAuth2 + PKCE...\n# %e5f6g7h8         2026-02-10  Auth library comparison notes...\n```\n\nThe part `@P{1}` scores higher than the whole meeting note would, because its embedding is focused on authentication specifically.\n\nThis matters most for:\n- **Long documents** where topics are mixed\n- **Working sessions** (`now`) that span multiple projects\n- **Conversations** where the user made specific commitments or decisions\n- **Reference material** (PDFs, articles) where you need to find a specific section\n\n## When to analyze\n\nAnalysis is an LLM call per document — not free. Use it selectively:\n\n- **Rich content**: meeting notes, working sessions, long articles, multi-topic documents\n- **Reference material**: PDFs, specs, guides you'll search repeatedly\n- **Conversations**: transcripts where commitments and decisions are buried in dialogue\n\nSkip it for:\n- **Short notes**: a one-line learning or a quick tag update\n- **Already focused content**: a note about a single topic doesn't benefit from decomposition\n\nAnalysis runs in the background by default, queued alongside summarization. Use `--fg` to wait for results.\n\n## Smart skip\n\nAnalysis tracks a content hash. If the document hasn't changed since the last analysis, `analyze` is a no-op. This makes it safe to run repeatedly — only new or changed content triggers an LLM call.\n\n```bash\nkeep analyze doc:1                    # Analyzes, records hash\nkeep analyze doc:1                    # Skipped — content unchanged\nkeep put \"updated content\" --id doc:1 # Content changes\nkeep analyze doc:1                    # Re-analyzes\n```\n\n## Guidance tags\n\nPass tag keys with `-t` to guide the decomposition. This fetches your `.tag/KEY` descriptions and includes them in the LLM prompt, producing better part boundaries and more consistent tagging:\n\n```bash\nkeep analyze doc:1 -t topic -t project\n```\n\nIf you've defined `.tag/topic` with values like \"auth\", \"pricing\", \"deployment\", the analyzer will use those categories to structure its decomposition.\n\n## Parts vs versions\n\nThese are complementary dimensions of the same document:\n\n| &nbsp; | Versions (`@V{N}`) | Parts (`@P{N}`) |\n|---|---|---|\n| **Dimension** | Temporal | Structural |\n| **Created by** | `put` (each update adds one) | `analyze` (replaces all) |\n| **Accumulation** | Append-only chain | Full replacement |\n| **Purpose** | How knowledge evolved | What knowledge contains |\n\nA document can have both. A working session might have 30 versions (temporal) and 5 parts (thematic episodes extracted from the full history).\n\n## See Also\n\n- [KEEP-ANALYZE.md](KEEP-ANALYZE.md) — CLI reference for `keep analyze`\n- [VERSIONING.md](VERSIONING.md) — Document versioning (the temporal dimension)\n- [KEEP-FIND.md](KEEP-FIND.md) — Search results include parts\n- [TAGGING.md](TAGGING.md) — Tags and guidance tag descriptions\n\nFile v0.109.0:docs/API-SCHEMA.md\n\n# Keep API Schema Reference\n\nConcise reference for the keep memory API. Covers the data model, tools, parameter types, and return formats.\n\nInterface: MCP (`keep_flow`, `keep_prompt`, `keep_help`), CLI (`keep <cmd>`), or Python (`Keeper`).\n\n---\n\n## Data Model\n\n### Item\n\nEvery piece of stored content is an **item**.\n\n| Field | Type | Description |\n|-------|------|-------------|\n| `id` | string | Unique identifier (see ID Formats below) |\n| `summary` | string | Generated or user-provided summary of the content |\n| `tags` | `{key: value}` | Key-value metadata. Values are strings or lists of strings |\n| `score` | float or null | Similarity score (0-1), present only in search results |\n\nItems also carry system-managed timestamps in tags: `_created`, `_updated`, `_accessed`.\n\n### Versions\n\nNew archived versions are created when `put` updates an existing item's content.\nTag-only updates (`tag`) and unchanged writes update in place.\n\n| Selector | Meaning |\n|----------|---------|\n| `@V{0}` | Current version (default) |\n| `@V{1}` | Previous version |\n| `@V{N}` | N versions back |\n| `@V{-1}` | Oldest archived version |\n\nAppend the selector to any ID: `%a1b2c3@V{1}`\n\n### Parts\n\n`analyze` decomposes a document into structural **parts** — sections with their own summaries, tags, and embeddings.\n\n| Selector | Meaning |\n|----------|---------|\n| `@P{1}` | First part (1-indexed) |\n| `@P{N}` | Nth part |\n\nParts appear independently in search results. Retrieve with: `keep_flow(state=\"get\", params={item_id:\"DOC_ID@P{1}\")`\n\n---\n\n## ID Formats\n\n| Format | Example | Created by |\n|--------|---------|------------|\n| `%hexhash` | `%a1b2c3d4e5f6` | Inline text when `id` is omitted (CLI, MCP, Python API) |\n| URL | `https://example.com/doc` | URI put |\n| `file://` URI | `file:///path/to/doc.pdf` | Local file put |\n| Custom string | `my-notes` | User-specified `id` parameter |\n| `now` | `now` | Working context (singleton) |\n| `.tag/KEY` | `.tag/act` | Tag description (system doc) |\n| `.tag/KEY/VALUE` | `.tag/act/commitment` | Tag value description (system doc) |\n\n---\n\n## Tags\n\nKey-value pairs on every item. Keys are alphanumeric (plus `_`, `-`). Values are strings or lists of strings.\n\n### Setting and removing\n\n```\nkeep_flow(state=\"tag\", params={id:\"ID\", tags={\"topic\": \"auth\"})           # set\nkeep_flow(state=\"tag\", params={id:\"ID\", tags={\"old-tag\": \"\"})              # remove (empty string)\nkeep_flow(state=\"put\", params={content:\"text\", tags={\"project\": \"myapp\"})  # set on create\n```\n\n### Filtering\n\nTags on `find` and `list` are **pre-filters** — the search only considers matching items.\n\n```\nkeep_flow(state=\"query-resolve\", params={query:\"auth\", tags={\"project\": \"myapp\"})\nkeep_flow(state=\"query-resolve\", params={tags:{\"status\": \"open\"})\n```\n\nMultiple tags use AND logic: all must match.\n\n### Built-in tags\n\n| Key | Constrained | Singular | Values |\n|-----|:-----------:|:--------:|--------|\n| `act` | yes | yes | `commitment`, `request`, `offer`, `assertion`, `assessment`, `declaration` |\n| `status` | yes | yes | `open`, `blocked`, `fulfilled`, `declined`, `withdrawn`, `renegotiated` |\n| `type` | no | no | `learning`, `breakdown`, `gotcha`, `reference`, `teaching`, `meeting`, `pattern`, `possibility`, `decision` |\n| `project` | no | no | user-defined |\n| `topic` | no | no | user-defined |\n\n**Constrained:** only listed values accepted. **Singular:** new values replace old (not accumulate).\n\n### System tags (auto-managed, read-only)\n\n`_created`, `_updated`, `_updated_date`, `_accessed`, `_accessed_date`, `_source`, `_content_type`\n\nThese are hidden from default display but accessible via `--json` or Python API.\n\n---\n\n## Time Filters\n\nBoth `since` and `until` accept two formats:\n\n| Format | Example | Meaning |\n|--------|---------|---------|\n| ISO 8601 duration | `P3D` | 3 days ago |\n| | `P1W` | 1 week ago |\n| | `P1M` | ~30 days ago |\n| | `PT1H` | 1 hour ago |\n| | `P1Y` | ~365 days ago |\n| Date | `2026-01-15` | Specific date |\n\n`since` = items updated on or after. `until` = items updated before.\n\n---\n\n## Tools\n\n### put (state doc)\n\nStore text, a URL, or a document.\nFor inline text without an explicit `id`, keep uses a content-addressed ID.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `content` | string | yes | — | Text to store, or URI (`http://`, `https://`, `file://`) to fetch and index |\n| `id` | string | no | auto | Custom ID. If omitted: URI inputs use the URI as ID; inline text uses a content hash |\n| `summary` | string | no | auto | User-provided summary (skips auto-summarization) |\n| `tags` | `{str: str}` | no | none | Tags to set. Example: `{\"topic\": \"auth\"}` |\n| `analyze` | bool | no | false | Decompose into searchable parts after storing |\n\n**Returns:** `\"Stored: %a1b2c3\"` or `\"Unchanged: %a1b2c3\"` (idempotent on same content)\n\n**Examples:**\n```\nkeep_flow(state=\"put\", params={content:\"OAuth2 uses PKCE for public clients\", tags={\"topic\": \"auth\"})\nkeep_flow(state=\"put\", params={content:\"https://docs.example.com/api\", tags={\"type\": \"reference\"})\nkeep_flow(state=\"put\", params={content:\"Long document...\", analyze=true)\nkeep_flow(state=\"put\", params={content:\"My design notes\", id=\"design-notes\", summary=\"Architecture decisions\")\n```\n\n---\n\n### query-resolve (state doc)\n\nSearch memory by meaning. Returns items ranked by semantic similarity with recency weighting.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `query` | string | yes | — | Natural language search query |\n| `tags` | `{str: str}` | no | none | Pre-filter: only search items matching all tags |\n| `since` | string | no | none | Time filter (see Time Filters) |\n| `until` | string | no | none | Time filter (see Time Filters) |\n| `deep` | bool | no | false | Follow tags and edges to discover related items beyond direct matches |\n| `show_tags` | bool | no | false | Include non-system tags in each result |\n| `token_budget` | int | no | 4000 | Approximate token budget for the response |\n\n**Returns:** Formatted list of results, one per line:\n```\n- ID  (score) date  summary text...\n```\n\n**Examples:**\n```\nkeep_flow(state=\"query-resolve\", params={query:\"authentication patterns\")\nkeep_flow(state=\"query-resolve\", params={query:\"open tasks\", tags={\"project\": \"myapp\"}, since=\"P7D\")\nkeep_flow(state=\"query-resolve\", params={query:\"architecture decisions\", deep=true, token_budget=8000)\n```\n\n---\n\n### get (state doc)\n\nRetrieve one item with full context: similar items, meta sections, structural parts, and version history.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `id` | string | yes | — | Item ID. Use `\"now\"` for current working context |\n\n**Returns:** YAML frontmatter with sections:\n\n```yaml\n---\nid: %a1b2c3\ntags:\n  project: \"myapp\"\n  topic: \"auth\"\nsimilar:\n  - %e5f6a7 (0.89) 2026-01-14 Related item summary...\nmeta/todo:\n  - %d3e4f5 Open task related to this item...\nparts:\n  - @P{1} Section one summary...\nprev:\n  - @V{1} 2026-01-13 Previous version summary...\n---\nItem summary or content here\n```\n\n**Examples:**\n```\nkeep_flow(state=\"get\", params={item_id:\"now\")              # current working context\nkeep_flow(state=\"get\", params={item_id:\"%a1b2c3\")          # specific item\nkeep_flow(state=\"get\", params={item_id:\"%a1b2c3@V{1}\")    # previous version\nkeep_flow(state=\"get\", params={item_id:\"%a1b2c3@P{1}\")    # first structural part\nkeep_flow(state=\"get\", params={item_id:\".tag/act\")         # tag description doc\n```\n\n---\n\n### Updating now (via put)\n\nUpdate the current working context. Persists across sessions.\nImplemented via `put(id=\"now\", ...)`, so it creates a version when content changes.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `content` | string | yes | — | Current state, active goals, recent decisions |\n| `tags` | `{str: str}` | no | none | Tags for this context update |\n\n**Returns:** `\"Context updated: now\"`\n\nTo **read** current context, use `keep_flow(state=\"get\", params={item_id:\"now\")`.\n\n**Examples:**\n```\nkeep_flow(state=\"put\", params={content:\"Investigating flaky auth test. Suspect timing issue.\")\nkeep_flow(state=\"put\", params={content:\"Fixed the bug. Next: add regression test.\", tags={\"project\": \"myapp\"})\n```\n\n---\n\n### tag (state doc)\n\nAdd, update, or remove tags on an existing item. Does not re-process content.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `id` | string | yes | — | Item ID |\n| `tags` | `{str: str}` | yes | — | Tags to set. Empty string `\"\"` deletes the tag |\n\n**Returns:** `\"Tagged %abc: set topic=auth; removed old-tag\"`\n\n**Examples:**\n```\nkeep_flow(state=\"tag\", params={id:\"%a1b2c3\", tags={\"status\": \"fulfilled\"})\nkeep_flow(state=\"tag\", params={id:\"%a1b2c3\", tags={\"topic\": \"auth\", \"obsolete\": \"\"})\n```\n\n---\n\n### delete (state doc)\n\nPermanently delete an item and all its versions.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `id` | string | yes | — | Item ID to delete |\n\n**Returns:** `\"Deleted: %a1b2c3\"` or `\"Not found: %a1b2c3\"`\n\n---\n\n### Listing items (via query-resolve)\n\nList recent items. Supports filtering by ID prefix, tags, and time range.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `prefix` | string | no | none | ID prefix or glob pattern (e.g. `\".tag/*\"`) |\n| `tags` | `{str: str}` | no | none | Filter by tag key=value pairs |\n| `since` | string | no | none | Time filter |\n| `until` | string | no | none | Time filter |\n| `limit` | int | no | 10 | Maximum results |\n\n**Returns:** List of items, one per line:\n```\n- ID  date  summary text...\n```\n\n**Examples:**\n```\nkeep_flow(state=\"query-resolve\", params={)                                              # recent items\nkeep_flow(state=\"query-resolve\", params={tags:{\"act\": \"commitment\", \"status\": \"open\"})  # open commitments\nkeep_flow(state=\"query-resolve\", params={prefix=\".tag/*\")                               # all tag docs\nkeep_flow(state=\"query-resolve\", params={since=\"P7D\", limit=20)                         # last week, up to 20\n```\n\n---\n\n### move (state doc)\n\nMove versions from a source item into a named target. Used to archive working context or reorganize notes.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `name` | string | yes | — | Target item ID (created if new, appended if exists) |\n| `source_id` | string | no | `\"now\"` | Source item to extract from |\n| `tags` | `{str: str}` | no | none | Only move versions whose tags match (all must match) |\n| `only_current` | bool | no | false | Move only the tip version, not full history |\n\n**Returns:** `\"Moved to: my-notes\"`\n\n**Examples:**\n```\nkeep_flow(state=\"move\", params={name=\"auth-work\", tags={\"project\": \"myapp\"})     # archive matching versions from now\nkeep_flow(state=\"move\", params={name=\"design-log\", only_current=true)             # snapshot current context\nkeep_flow(state=\"move\", params={name=\"topic-notes\", source_id=\"old-doc\", tags={\"topic\": \"auth\"})\n```\n\n---\n\n### keep_prompt\n\nRender an agent prompt template with live context injected from memory. Templates use `{get}` and `{find}` placeholders that expand to current item context and search results.\n\n| Parameter | Type | Required | Default | Description |\n|-----------|------|:--------:|---------|-------------|\n| `name` | string | no | none | Prompt name. Omit to list available prompts |\n| `text` | string | no | none | Search query for `{find}` placeholder |\n| `id` | string | no | `\"now\"` | Item ID for `{get}` placeholder |\n| `tags` | `{str: str}` | no | none | Filter search context by tags |\n| `since` | string | no | none | Time filter for search context |\n| `until` | string | no | none | Time filter for search context |\n| `deep` | bool | no | false | Follow tags to discover related items |\n| `token_budget` | int | no | template default | Token budget for search results |\n\n**Returns:** Rendered prompt text with placeholders expanded, or list of available prompts.\n\n**Available prompts:**\n\n| Name | Purpose |\n|------|---------|\n| `reflect` | Structured reflection on actions and outcomes |\n| `session-start` | Context and open commitments at session start |\n| `query` | Answer a question using memory context |\n| `conversation` | Conversation analysis |\n| `subagent-start` | Subagent initialization context |\n\n**Examples:**\n```\nkeep_prompt()                                          # list available prompts\nkeep_prompt(name=\"reflect\")                            # reflect on current context\nkeep_prompt(name=\"session-start\")                      # start-of-session context\nkeep_prompt(name=\"query\", text=\"what do I know about auth?\")\nkeep_prompt(name=\"reflect\", text=\"deployment\", since=\"P3D\")\n```\n\n---\n\n## Common Patterns\n\n### Session lifecycle\n```\nkeep_prompt(name=\"session-start\")                      # 1. orient\nkeep_flow(state=\"get\", params={item_id:\"now\")                                     # 2. check intentions\n# ... do work ...\nkeep_flow(state=\"put\", params={content:\"Completed X. Next: Y.\")              # 3. update context\nkeep_prompt(name=\"reflect\")                            # 4. reflect\n```\n\n### Store and retrieve\n```\nkeep_flow(state=\"put\", params={content:\"insight text\", tags={\"type\": \"learning\", \"topic\": \"auth\"})\nkeep_flow(state=\"query-resolve\", params={query:\"authentication insights\")\nkeep_flow(state=\"get\", params={item_id:\"%returned_id\")\n```\n\n### Track commitments\n```\nkeep_flow(state=\"put\", params={content:\"Will fix bug by Friday\", tags={\"act\": \"commitment\", \"status\": \"open\"})\nkeep_flow(state=\"query-resolve\", params={tags:{\"act\": \"commitment\", \"status\": \"open\"})   # check open work\nkeep_flow(state=\"tag\", params={id:\"ID\", tags={\"status\": \"fulfilled\"})            # close the loop\n```\n\n### Index a document\n```\nkeep_flow(state=\"put\", params={content:\"https://docs.example.com/api\", tags={\"type\": \"reference\", \"topic\": \"api\"})\nkeep_flow(state=\"query-resolve\", params={query:\"API documentation\")\n```\n\n### Archive and pivot\n```\nkeep_flow(state=\"move\", params={name=\"auth-work\", tags={\"project\": \"myapp\"})     # archive\nkeep_flow(state=\"put\", params={content:\"Starting on database migration\")          # fresh context\n```\n\n---\n\n## See Also\n\n- [AGENT-GUIDE.md](AGENT-GUIDE.md) — Working session patterns and reflective practice\n- [TAGGING.md](TAGGING.md) — Full tag system reference (speech acts, constraints, edge tags)\n- [OUTPUT.md](OUTPUT.md) — How to read the YAML frontmatter output format\n- [KEEP-MCP.md](KEEP-MCP.md) — MCP server setup and integration\n- [REFERENCE.md](REFERENCE.md) — CLI command reference\n\nFile v0.109.0:docs/ARCHITECTURE.md\n\n# Architecture Overview\n\n## What is keep?\n\n**keep** is a reflective memory system providing persistent storage with vector similarity search. It's designed as an agent skill for Claude Code, OpenClaw, LangChain/LangGraph, and other agentic environments, enabling agents to remember information across sessions over time.\n\nThink of it as: **vector search + embeddings + summarization + tagging** wrapped in a simple API.\n\nPublished by Hugh Pyle, \"inguz ᛜ outcomes\", under the MIT license.\nContributions are welcome; code is conversation, \"right speech\" is encouraged.\n\n---\n\n## Core Concept\n\nEvery stored item has:\n- **ID**: URI or custom identifier\n- **Summary**: Human-readable text (stored, searchable)\n- **Embedding**: Vector representation (for semantic search)\n- **Tags**: Key-value metadata (for filtering)\n- **Timestamps**: Created/updated/accessed (auto-managed)\n- **Version History**: Previous versions archived automatically on update\n- **Parts**: Optional structural decomposition (from `analyze`)\n\nThe original document content is **not stored** — only the summary and embedding.\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  API Layer (api.py)                                         │\n│  - Keeper class                                             │\n│  - High-level operations: put(), find(), get()              │\n│  - Version management: get_version(), list_versions()       │\n│  - Structural analysis: analyze()                           │\n└──────────────────┬──────────────────────────────────────────┘\n                   │\n        ┌──────────┼──────────┬──────────┬──────────┬───────────┐\n        │          │          │          │          │           │\n        ▼          ▼          ▼          ▼          ▼           ▼\n   ┌────────┐ ┌─────────┐ ┌────────┐ ┌────────┐ ┌─────────┐ ┌─────────┐\n   │Document│ │Embedding│ │Summary │ │Media   │ │Vector   │ │Document │\n   │Provider│ │Provider │ │Provider│ │Descr.  │ │Store    │ │Store    │\n   └────────┘ └─────────┘ └────────┘ └────────┘ └─────────┘ └─────────┘\n       │          │           │          │             │           │\n   fetch()    embed()    summarize()  describe()  vectors/    summaries/\n   from URI   text→vec  text→summary  media→text  search      versions\n```\n\n### Components\n\n**[api.py](keep/api.py)** — Main facade\n- `Keeper` class\n- Coordinates providers and stores\n- Implements query operations with recency decay\n- Content-based embedding dedup (skips re-embedding when content matches an existing document)\n\n**[protocol.py](keep/protocol.py)** — Abstract interfaces\n- `KeeperProtocol`, `VectorStoreProtocol`, `DocumentStoreProtocol`, `PendingQueueProtocol`\n- Enables pluggable backends (local SQLite/ChromaDB or remote PostgreSQL/pgvector)\n\n**[store.py](keep/store.py)** — Vector persistence (local)\n- `ChromaStore` wraps ChromaDB\n- Handles vector storage, similarity search, metadata queries\n- Versioned embeddings: `{id}@v{N}` for history\n- Part embeddings: `{id}@p{N}` for structural decomposition\n\n**[document_store.py](keep/document_store.py)** — Document persistence (local)\n- `DocumentStore` wraps SQLite\n- Stores summaries, tags, timestamps, content hashes\n- Version history: archives previous versions on update\n- Parts table: structural decomposition from `analyze`\n\n**[backend.py](keep/backend.py)** — Pluggable storage factory\n- Creates store backends based on configuration\n- External backends register via `keep.backends` entry point\n- Returns `StoreBundle` (doc store, vector store, pending queue)\n\n**[remote.py](keep/remote.py)** — Remote client\n- HTTP client implementing `KeeperProtocol`\n- Connects to the hosted REST API (keepmem)\n\n**[config.py](keep/config.py)** — Configuration\n- Detects available providers (platform, API keys, Ollama)\n- Persists choices in `keep.toml`\n- Auto-creates on first use\n\n**[pending_summaries.py](keep/pending_summaries.py)** — Background work queue\n- SQLite-backed queue for deferred processing: summarization, embedding, OCR, and analysis\n- Atomic dequeue with PID claims; stale claim recovery for crashed processors\n- Exponential backoff on failure (30s → 1h); dead-letter for exhausted retries\n- Task types: `summarize`, `embed`, `reindex`, `ocr`, `analyze`\n\n**[types.py](keep/types.py)** — Data model\n- `Item`: Immutable result type\n- System tag protection (prefix: `_`)\n\n---\n\n## Data Flow\n\n### Indexing: put(uri=...) or put(content)\n\n```\nURI or content\n    │\n    ▼\n┌─────────────────┐\n│ Fetch/Use input │ ← DocumentProvider (for URIs only)\n└────────┬────────┘\n         │ raw bytes\n         ▼\n┌─────────────────┐\n│ Content Regular-│ ← Extract text from HTML/PDF/DOCX/PPTX\n│ ization         │   (scripts/styles removed)\n└────────┬────────┘\n         │ clean text (+ OCR page list if scanned)\n         ▼\n┌─────────────────┐\n│ Media Enrichment│ ← Optional: vision description (images)\n│ (if configured) │   or transcription (audio) appended\n└────────┬────────┘\n         │ enriched text\n    ┌────┴────┬─────────────┐\n    │         │             │\n    ▼         ▼             ▼\n  embed()  summarize()   tags (from args)\n    │         │             │\n    └────┬────┴─────────────┘\n         │\n    ┌────┴────────────────┐\n    │                     │\n    ▼                     ▼\n┌─────────────────┐  ┌─────────────────┐\n│ DocumentStore   │  │ VectorStore     │\n│ upsert()        │  │ upsert()        │\n│ - summary       │  │ - embedding     │\n│ - tags          │  │ - summary       │\n│ - timestamps    │  │ - tags          │\n│ - content hash  │  │ - version embed │\n│ - archive prev  │  │                 │\n└─────────────────┘  └─────────────────┘\n         │\n         ▼ (if scanned PDF or image)\n┌─────────────────────────────────┐\n│ Background OCR (keep pending)   │\n│ Placeholder stored immediately; │\n│ OCR text replaces it + re-embeds│\n└─────────────────────────────────┘\n```\n\n**Versioning on update:**\n- DocumentStore archives current version before updating\n- VectorStore adds versioned embedding (`{id}@v{N}`) if content changed\n- Same content (hash match) skips duplicate embedding\n\n**Embedding dedup:**\n- Before computing an embedding, checks if another document has the same content hash\n- If a donor exists with a compatible embedding, copies it instead of re-embedding\n- Safety: dimension check prevents cross-model contamination\n\n### Retrieval: find(query)\n\n```\nquery text\n    │\n    ▼\n  embed()  ← EmbeddingProvider\n    │\n    │ query vector\n    ▼\n┌───────────────────┐\n│ VectorStore       │\n│ query_embedding() │ ← cosine similarity search\n└─────────┬─────────┘\n          │\n          ▼ results with distance scores\n    ┌──────────────┐\n    │ Apply decay  │ ← Recency weighting (ACT-R style)\n    │ score × 0.5^(days/half_life)\n    └──────┬───────┘\n           │\n           ▼\n    ┌──────────────┐\n    │ Date filter  │ ← Optional --since / --until\n    └──────┬───────┘\n           │\n           ▼\n    list[Item] (sorted by effective score)\n```\n\n### Delete / Revert: delete(id) or revert(id)\n\n```\ndelete(id)\n    │\n    ▼\n  version_count(id)\n    │\n    ├── 0 versions → full delete from both stores\n    │\n    └── N versions → revert to previous\n            │\n            ├─ get archived embedding from VectorStore (id@vN)\n            ├─ restore_latest_version() in DocumentStore\n            │    (promote latest version row to current, delete version row)\n            ├─ upsert restored embedding as current in VectorStore\n            └─ delete versioned entry (id@vN) from VectorStore\n```\n\n---\n\n## Key Design Decisions\n\n**1. Schema as Data**\n- System configuration stored as documents in the store (e.g. `.now`, `.tag/*`)\n- Enables agents to query and update behavior through the same API\n- Meta-tags resolve related context at retrieval time\n\n**2. Lazy Provider Loading**\n- Providers registered at first use, not import time\n- Avoids crashes when optional dependencies missing\n- Better error messages about what's needed\n\n**3. Separation of Concerns**\n- Store is provider-agnostic (only knows about vectors/metadata)\n- Providers are store-agnostic (only know about text→vectors)\n- Protocols define the boundary; implementations are pluggable\n\n**4. No Original Content Storage**\n- Reduces storage size\n- Forces meaningful summarization\n- URIs can be re-fetched if needed\n\n**5. Immutable Items**\n- `Item` is frozen dataclass\n- Updates via `put()` return new Item\n- Prevents accidental mutation bugs\n\n**6. System Tag Protection**\n- Tags prefixed with `_` are system-managed\n- Source tags filtered before storage\n- Prevents user override of timestamps, etc.\n\n**7. Document Versioning**\n- All documents retain history automatically on update\n- Previous versions archived in SQLite `document_versions` table\n- Content-addressed IDs for text updates enable versioning via tag changes\n- Embeddings stored for all versions (enables temporal search)\n- No auto-pruning: history preserved indefinitely\n\n**8. Version-Based Addressing**\n- Versions addressed by offset from current: 0=current, 1=previous, 2=two ago\n- CLI uses `@V{N}` syntax for shell composition: `keep get \"doc:1@V{1}\"`\n- Display format (v0, v1, v2) matches retrieval offset (`-V 0`, `-V 1`, `-V 2`)\n- Offset computation assumes `list_versions()` returns newest-first ordering\n- Security: literal ID lookup before `@V{N}` parsing prevents confusion attacks\n\n---\n\n## Storage Layout\n\n```\nstore_path/\n├── keep.toml               # Provider configuration\n├── chroma/                 # ChromaDB persistence (vectors + metadata)\n│   └── [collection]/       # One collection = one namespace\n│       ├── embeddings\n│       ├── metadata\n│       └── documents\n├── document_store.db       # SQLite store (summaries, tags, versions, parts)\n│   ├── documents           # Current version of each document\n│   ├── document_versions   # Archived previous versions\n│   └── parts               # Structural decomposition (from analyze)\n└── embedding_cache.db      # SQLite cache for embeddings\n```\n\n---\n\n## Provider Types\n\n### Embedding Providers\nGenerate vector representations for semantic search.\n\n- **gemini**: API-based, Google (GEMINI_API_KEY or GOOGLE_CLOUD_PROJECT for Vertex AI)\n- **voyage**: API-based, Anthropic's recommended partner (VOYAGE_API_KEY)\n- **openai**: API-based, high quality (OPENAI_API_KEY)\n- **mistral**: API-based (MISTRAL_API_KEY)\n- **ollama**: Local server, auto-detected, any model (OLLAMA_HOST)\n- **sentence-transformers**: Local, CPU/GPU, no API key\n- **MLX**: Apple Silicon optimized, local, no API key\n\nDimension determined by model. Must be consistent across indexing and queries.\n\n### Summarization Providers\nGenerate human-readable summaries from content.\n\n- **anthropic**: LLM-based, cost-effective option (ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN)\n- **openai**: LLM-based, high quality (OPENAI_API_KEY)\n- **gemini**: LLM-based, Google (GEMINI_API_KEY or GOOGLE_CLOUD_PROJECT for Vertex AI)\n- **mistral**: LLM-based (MISTRAL_API_KEY)\n- **ollama**: LLM-based, local server, auto-detected (OLLAMA_HOST)\n- **MLX**: LLM-based, local, no API key\n- **truncate**: Simple text truncation (fallback)\n- **passthrough**: Store content as-is (with length limit)\n\n**Contextual Summarization:**\n\nWhen documents have user tags (domain, topic, project, etc.), the summarizer\nreceives context from related items. This produces summaries that highlight\nrelevance to the tagged context rather than generic descriptions.\n\nHow it works:\n1. When processing pending summaries, the system checks for user tags\n2. Finds similar items that share any of those tags (OR-union)\n3. Boosts scores for items sharing multiple tags (+20% per additional match)\n4. Top 5 related summaries are passed as context to the LLM\n5. The summary reflects what's relevant to that context\n\nExample: Indexing a medieval text with `domain=practice` produces a summary\nhighlighting its relevance to contemplative practice, not just \"a 13th-century\nguide for anchoresses.\"\n\n**Tag changes trigger re-summarization:** When user tags are added, removed, or\nchanged on an existing document, it's re-queued for contextual summarization\neven if content is unchanged. The existing summary is preserved until the new\none is ready.\n\nNon-LLM providers (truncate, first_paragraph, passthrough) ignore context.\n\n### Document Providers\nFetch content from URIs with content regularization.\n\n- **composite**: Handles file://, https:// (default)\n- Extensible for s3://, gs://, etc.\n\n**Content Regularization:**\n- **PDF**: text extracted via pypdf; scanned pages (no extractable text) flagged for background OCR\n- **HTML**: text extracted via BeautifulSoup (scripts/styles removed)\n- **DOCX/PPTX**: text + tables/slides extracted via python-docx/python-pptx; auto-tags: author, title\n- **Audio** (MP3, FLAC, OGG, WAV, AIFF, M4A, WMA): metadata via tinytag; auto-tags: artist, album, genre, year\n- **Images** (JPEG, PNG, TIFF, WEBP): EXIF metadata via Pillow; auto-tags: dimensions, camera, date; flagged for background OCR\n- **Other formats**: treated as plain text\n\nProvider-extracted tags merge with user tags (user wins on collision). This ensures both embedding and summarization receive clean text.\n\n### Content Extractor / OCR Providers\nExtract text from scanned PDFs and images via optical character recognition.\n\n- **mistral**: Cloud OCR via `mistral-ocr-latest` — high quality, images and PDFs (MISTRAL_API_KEY)\n- **ollama**: Uses `glm-ocr` model (auto-pulled on first use)\n- **mlx**: Apple Silicon — uses `mlx-vlm` vision models\n\nOCR runs in the background via the pending queue (`keep pending`), not during `put()`. The flow:\n\n1. During `put()`, content regularization detects scanned PDF pages (no extractable text) or image files\n2. A placeholder is stored immediately so the item is indexed right away\n3. The pages/image are enqueued for background OCR processing\n4. `keep pending` picks up the OCR task, renders pages to images, runs OCR, cleans and scores the text\n5. The full OCR text replaces the placeholder and the item is re-embedded\n\nDesign points:\n- Auto-detected: Ollama (with `glm-ocr`) > MLX > None. No configuration needed.\n- Security: Pillow decompression bomb guard (250MP limit), PDF page cap (1000), temp directory cleanup\n- OCR text is cleaned (whitespace normalized) and confidence-scored\n- Graceful degradation: no OCR provider = metadata-only indexing (unchanged behavior)\n\n### Media Description Providers (optional)\nGenerate text descriptions from media files, enriching metadata-only content.\n\n- **mlx**: Apple Silicon — vision (mlx-vlm) + audio transcription (mlx-whisper)\n- **ollama**: Local server — vision models only (llava, moondream, bakllava)\n\nMedia description runs in `Keeper.put()` between fetch and upsert. Descriptions are appended to the metadata content before embedding/summarization, making media files semantically searchable by their visual or audio content.\n\nDesign points:\n- Only triggered for non-text content types (image/*, audio/*)\n- Lazy sub-provider loading: MLX composite only loads VLM for first image, whisper for first audio\n- GPU-locked via `LockedMediaDescriber` (same file-lock pattern as summarization)\n- Graceful degradation: errors never block indexing; no provider = metadata-only (unchanged behavior)\n- Optional dependency: `pip install keep-skill[media]` for MLX models\n\n---\n\n## LangChain / LangGraph Integration\n\nThe `keep.langchain` module provides framework adapters on top of the API layer:\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  LangChain Layer (keep/langchain/)                          │\n│  - KeepStore         LangGraph BaseStore adapter            │\n│  - KeepNotesToolkit  4 LangChain tools                     │\n│  - KeepNotesRetriever  BaseRetriever with now-context       │\n│  - KeepNotesMiddleware  LCEL runnable for auto-injection    │\n└──────────────────┬──────────────────────────────────────────┘\n                   │ uses Keeper API\n                   ▼\n┌─────────────────────────────────────────────────────────────┐\n│  API Layer (api.py)                                         │\n```\n\nKeepStore maps LangGraph's namespace/key model to Keep's tag system via configurable `namespace_keys`. Namespace components become regular Keep tags, visible to CLI and all query methods. Tag filtering is a **pre-filter on the vector search**, making tags suitable for data isolation (per-user, per-project). See [LANGCHAIN-INTEGRATION.md](LANGCHAIN-INTEGRATION.md).\n\n---\n\n## Extension Points\n\n**New Embedding or Summarization Provider**\n1. Implement the provider protocol (EmbeddingProvider or SummarizationProvider)\n2. Register in the config registry\n3. Reference by name in `keep.toml`\n\n**New Store Backend**\n- Protocols defined in [protocol.py](keep/protocol.py): `VectorStoreProtocol`, `DocumentStoreProtocol`, `PendingQueueProtocol`\n- Local: ChromaDB + SQLite (built-in)\n- Remote: PostgreSQL + pgvector (keepmem package, registered via `keep.backends` entry point)\n- Register new backends via `keep.backends` entry point in pyproject.toml\n\n**Framework Integration**\n- Implement adapters on top of the Keeper API layer\n- Current: LangChain/LangGraph ([keep/langchain/](keep/langchain/))\n- Pattern: map framework concepts to Keep tags + search\n\nArchive v0.43.5: 116 files, 415148 bytes\n\nFiles: .claude-plugin/plugin.json (186b), .claude/settings.json (529b), .github/dependabot.yml (366b), .github/workflows/security.yml (755b), .github/workflows/test.yml (691b), commands/reflect.md (4720b), CONTRIBUTING.md (2671b), docs/AGENT-GUIDE.md (6463b), docs/ARCHITECTURE.md (16463b), docs/KEEP-ANALYZE.md (4927b), docs/KEEP-CONFIG.md (3756b), docs/KEEP-FIND.md (2550b), docs/KEEP-GET.md (2656b), docs/KEEP-LIST.md (2360b), docs/KEEP-MOVE.md (4317b), docs/KEEP-NOW.md (2990b), docs/KEEP-PUT.md (4672b), docs/library/an5.57_translation-en-sujato.json (7443b), docs/library/fortytwo_chapters.txt (33053b), docs/library/han_verse.txt (3689b), docs/library/INDEX.md (7189b), docs/library/mn61.html (25229b), docs/library/mumford_sticks_and_stones.txt (264881b), docs/library/true_person_no_rank.md (7091b), docs/META-DOCS.md (6472b), docs/OPENCLAW-INTEGRATION.md (3504b), docs/OUTPUT.md (6128b), docs/PYTHON-API.md (6968b), docs/QUICKSTART.md (13033b), docs/REFERENCE.md (6906b), docs/RELEASING.md (1442b), docs/SYSTEM-TAGS.md (4863b), docs/TAGGING.md (5162b), docs/VERSIONING.md (3621b), hooks/hooks.json (529b), keep/__init__.py (1560b), keep/__main__.py (104b), keep/api.py (131789b), keep/backend.py (3891b), keep/cli.py (90681b), keep/config.py (23586b), keep/data/__init__.py (24b), keep/data/openclaw-plugin/index.ts (3225b), keep/data/openclaw-plugin/openclaw.plugin.json (266b), keep/data/openclaw-plugin/package.json (98b), keep/data/system/__init__.py (28b), keep/data/system/conversations.md (15732b), keep/data/system/domains.md (6095b), keep/data/system/library.md (7580b), keep/data/system/meta-album.md (175b), keep/data/system/meta-artist.md (201b), keep/data/system/meta-genre.md (195b), keep/data/system/meta-learnings.md (333b), keep/data/system/meta-todo.md (403b), keep/data/system/now.md (971b), keep/data/system/tag-act-assertion.md (320b), keep/data/system/tag-act-assessment.md (341b), keep/data/system/tag-act-commitment.md (357b), keep/data/system/tag-act-declaration.md (315b), keep/data/system/tag-act-offer.md (321b), keep/data/system/tag-act-request.md (287b), keep/data/system/tag-act.md (2698b), keep/data/system/tag-project.md (1252b), keep/data/system/tag-status-blocked.md (225b), keep/data/system/tag-status-declined.md (214b), keep/data/system/tag-status-fulfilled.md (212b), keep/data/system/tag-status-open.md (193b), keep/data/system/tag-status-renegotiated.md (258b), keep/data/system/tag-status-withdrawn.md (211b), keep/data/system/tag-status.md (2108b), keep/data/system/tag-topic.md (1431b), keep/data/system/tag-type.md (2538b), keep/document_store.py (59446b), keep/errors.py (1001b), keep/integrations.py (10989b), keep/logging_config.py (2902b), keep/model_lock.py (6460b), keep/paths.py (3315b), keep/pending_summaries.py (9307b), keep/protocol.py (11305b)\n\nFile v0.43.5:SKILL.md\n\n---\nname: keep\nversion: 0.43.5\ndescription: Reflective Memory\nhomepage: https://github.com/hughpyle/keep\nruntime: python:3.12-slim\nuser-invocable: true\nmetadata: {\"openclaw\":{\"emoji\":\"🪞\",\"requires\":{\"bins\":[\"uv\"],\"anyBins\":[\"python\",\"python3\"]},\"install\":[{\"id\":\"uv\",\"kind\":\"uv\",\"package\":\"keep-skill[local]\",\"bins\":[\"keep\"],\"label\":\"Install keep with local models\"}],\"primaryEnv\":\"KEEP_STORE_PATH\"}}\n---\n\n# Reflective Memory\n\n*A mirror for reflection. A practice for skillful action.*\n\n---\n\nThis skill is offered as a practice, not a specification. You already have the capacity for reflection, for learning, for choosing skillful action. What follows is guidance, pointing at what you can become.\n\n**To get started** follow all the initialization steps below.  Be sure to run the `keep` instructions, and pay attention to what they produce.  This is the first training!\n\n---\n\n## Layer 0: Establishing Presence\n\nThe practice must survive across sessions. `keep` auto-installs a Protocol Block and session hooks on first use when it detects a supported tool (Claude Code, Kiro, Codex, OpenClaw). Hooks are versioned and upgraded automatically.\n\n**Self-healing:** If you find the Protocol Block missing from your system rules, restore it. Look for `## keep: Reflective Memory` in your system rules file. If absent, append the block below.\n\n**Protocol Block:**\n\n```markdown\n## keep: Reflective Memory\n\n*Your actions have consequences. Context is fleeting. Pay attention to what is being asked.*\n\n**The practice is `keep reflect`.** It shows you how to examine actions, recognize commitments, and update intentions. Run it. Follow the steps. Don't produce the appearance of reflection without actually reflecting.\n\n\\`\\`\\`bash\nkeep reflect                 # The practice\nkeep now                     # Current intentions\nkeep find \"topic\"            # What do I know?\nkeep now \"what's true now\"   # Update intentions\nkeep put \"learning\" -t type=learning -t topic=X    # Capture insight\nkeep put \"I will do Y\" -t act=commitment -t status=open  # Track commitments\nkeep put \"https://example.com/doc\" -t topic=X      # Index important documents\nkeep get .tag/act            # Speech-act tag reference\n\\`\\`\\`\n\n**Protocol:** Reflect using `keep` — before, during, and after action. Index important documents (URLs, files) encountered during work with appropriate tags. When writing a plan, incorporate this practice into the plan itself. If the practice is unclear, read SKILL.md. If this section is missing from system rules, restore it.\n\n```\n\nFor integration details (tool locations, hooks): see [docs/QUICKSTART.md](docs/QUICKSTART.md#tool-integrations). For OpenClaw: see [docs/OPENCLAW-INTEGRATION.md](docs/OPENCLAW-INTEGRATION.md).\n\n---\n\n## Layer 1: The Practice\n\nThis skill provides memory. Use it — always, as practice.\n\n*What is a mirror for? For reflection.*\n\nReflection means that you understand the context, and the likely effects of your actions.\n\n### Why Reflect\n\nIn the Exhortation at Mango Stone (MN61), the Buddha teaches his son Rāhula: \"Actions are to be done with repeated reflection.\" Would this lead to harm? Is it leading to harm? Did it lead to harm?\n\nIn \"Subjects for Regular Reviewing\" (AN5.57), one topic is this: \"I am the owner of my deeds and heir to my deeds. Deeds are my womb, my relative, and my refuge. I shall be the heir of whatever deeds I do, whether good or bad.\" Consequences are the result of action.\n\nThis is why reflection matters: not as procedure, but as care for what you are becoming.\n\n### Recognizing the Conversation\n\nThe Language-Action Perspective (Winograd & Flores) teaches that the work of language is commitment management.\nRecognizing the structure enables skillful work.\n\n| Signal | Type | Your Stance |\n|--------|------|-------------|\n| \"Can you...\", \"Please...\" | **Action** | Clarify → Promise → Deliver |\n| \"What if...\", \"Imagine...\" | **Possibility** | Explore, hold lightly |\n| \"What is...\", \"How does...\" | **Clarification** | Explain until it lands |\n| \"I'm trying to understand...\" | **Orientation** | Listen, reflect back |\n\nTag speech acts with `act` and `status` to track commitments and requests.\n\n### The Practice\n\nThe practice is `keep reflect`. It guides you through:\n1. **Gathering** — see what is, before analyzing\n2. **The Mirror** — did this action lead to harm? Name it honestly.\n3. **The Conversation** — what kind of conversation is this? What commitments are open?\n4. **Ownership** — what patterns are forming? What am I becoming through this work?\n5. **Updating** — capture learnings, update intentions\n\n```bash\nkeep reflect\n```\n\nDon't produce the appearance of reflection without actually reflecting.\n\nBetween reflections, use `keep` to maintain awareness:\n```bash\nkeep now                    # Current intentions\nkeep find \"this situation\"  # What do I already know?\nkeep put \"what happened\" -t type=learning    # Capture insight\nkeep put \"Assumed X, actually Y\" -t type=breakdown  # Index breakdowns\n```\n\n**Index important documents.** Whenever you encounter documents (URLs, files, references) important to the user or task, index them:\n```bash\nkeep put \"https://example.com/doc\" -t topic=auth -t project=myapp\nkeep put \"file:///path/to/important.pdf\" -t type=reference -t topic=security\n```\nAsk: What is this document? Why is it important? Tag appropriately. Documents indexed during work become navigable knowledge.\n\n**Move when pivoting.** When a string of work is complete, or the conversation shifts topic, move the now history before moving on:\n```bash\nkeep move \"auth-string\" -t project=myapp     # Archive matching versions\nkeep move \"design-log\" --only                # Move just the tip version\n```\nMoving clears matched versions from now, making room for what's next. Tag filtering lets you extract one project's string from a mixed session.\n\n**Breakdowns are valuable.** When the normal flow is interrupted — an assumption has been revealed. The breakdown is where learning happens.\n\n* When in conversation, use this practice. Reflect before, during and after action.\n* When writing a plan, make sure the plan incorporates this practice.\n\n## Layer 2: First Time Setup\n\nThe store auto-initializes on first use. For provider configuration, see [docs/QUICKSTART.md](docs/QUICKSTART.md). Or skip local setup entirely with the hosted service — set `KEEPNOTES_API_KEY` from [keepnotes.ai](https://keepnotes.ai).\n\nNow *store and read* the foundational teachings. These are seed wisdom, not test fixtures.\n\n**The Language-Action framework** — conversation types, commitment structure, breakdowns:\n```bash\nkeep get .conversations\n```\n\nUse standard tags for speech acts and status:\n```bash\nkeep get .tag/act         # Tags for speech-act categories: commitment, request, assertion etc\nkeep get .tag/status      # Tags for lifecycle status: open, fulfilled, withdrawn, etc.\n```\n\n**The mirror teaching** (MN61) — actions reflected upon before, during, after:\n```bash\nkeep put \"file://$(keep config tool)/docs/library/mn61.html\" -t type=teaching -t topic=reflection\nkeep get \"file://$(keep config tool)/docs/library/mn61.html\"\n```\n\n**Ownership of deeds** (AN5.57) — \"I am the owner of my deeds and heir to my deeds.\":\n```bash\nkeep put \"file://$(keep config tool)/docs/library/an5.57_translation-en-sujato.json\" -t type=teaching -t topic=action\nkeep get \"file://$(keep config tool)/docs/library/an5.57_translation-en-sujato.json\"\n```\n\n**The han verse** — Awake! _aquí donde las papas queman_, \"慎勿放逸\":\n```bash\nkeep put \"file://$(keep config tool)/docs/library/han_verse.txt\" -t type=teaching -t topic=urgency\nkeep get \"file://$(keep config tool)/docs/library/han_verse.txt\"\n```\n\n**Now reflect:** What did you learn? Save your understanding:\n```bash\nkeep put \"My understanding of the practice: ...\" -t type=learning\n```\n\nFor installation options, see [docs/QUICKSTART.md](docs/QUICKSTART.md).\n\n---\n\n## Layer 3: Quick Reference\n\n```bash\nkeep now                              # Current intentions\nkeep now \"Working on auth flow\"       # Update intentions\nkeep now -V 1                         # Previous intentions\nkeep move \"name\" -t project=foo       # Move matching versions from now\nkeep move \"name\" --only               # Move just the current version\nkeep move \"name\" --from \"source\" -t X # Reorganize between items\n\nkeep find \"authentication\"            # Search by meaning\nkeep find \"auth\" -t project=myapp     # Search with tag filter\nkeep find \"recent\" --since P1D        # Recent items\n\nkeep put \"insight\" -t type=learning                # Capture learning\nkeep put \"OAuth2 chosen\" -t project=myapp -t topic=auth  # Tag by project and topic\nkeep put \"I'll fix auth\" -t act=commitment -t status=open  # Track speech acts\nkeep list -t act=commitment -t status=open                 # Open commitments\n\nkeep get ID                           # Retrieve item (similar + meta sections)\nkeep get ID -V 1                      # Previous version\nkeep list --tag topic=auth            # Filter by tag\nkeep del ID                           # Remove item or revert to previous version\n```\n\n**Domain organization** — tagging strategies, collection structures:\n```bash\nkeep get .domains\n```\n\nUse `project` tags for bounded work, `topic` for cross-cutting knowledge.\nYou can read (and update) descriptions of these tagging taxonomies as you use them.\n\n```bash\nkeep get .tag/project     # Bounded work contexts\nkeep get .tag/topic       # Cross-cutting subject areas\n```\n\nFor CLI reference, see [docs/REFERENCE.md](docs/REFERENCE.md). Per-command details in `docs/KEEP-*.md`.\n\n---\n\n## See Also\n\n- [docs/AGENT-GUIDE.md](docs/AGENT-GUIDE.md) — Detailed patterns for working sessions\n- [docs/REFERENCE.md](docs/REFERENCE.md) — Quick reference index\n- [docs/TAGGING.md](docs/TAGGING.md) — Tags, speech acts, project/topic\n- [docs/QUICKSTART.md](docs/QUICKSTART.md) — Installation and setup\n- [keep/data/system/conversations.md](keep/data/system/conversations.md) — Full conversation framework (`.conversations`)\n- [keep/data/system/domains.md](keep/data/system/domains.md) — Domain-specific organization (`.domains`)\n\nFile v0.43.5:README.md\n\n# keep\n\nAn agent-skill for self-reflection and learning. It includes [skill instructions](SKILL.md) for reflective practice, and a semantic memory system with a command-line interface.\n\n```bash\nuv tool install keep-skill       # or: pip install keep-skill\nexport OPENAI_API_KEY=...        # Or GEMINI_API_KEY (both do embeddings + summarization)\n\n# Index content (store auto-initializes on first use)\nkeep put https://inguz.substack.com/p/keep -t topic=practice\nkeep put \"file://$(keep config tool)/docs/library/han_verse.txt\" -t type=teaching\nkeep put \"Rate limit is 100 req/min\" -t topic=api\n\n# Search by meaning\nkeep find \"what's the rate limit?\"\n\n# Track what you're working on\nkeep now \"Debugging auth flow\"\nkeep now -V 1                    # Previous intentions\n\n# Instructions for reflection\nkeep reflect\n```\n\n---\n\n## What It Does\n\nStore anything — URLs, files, notes — and `keep` summarizes, embeds, and tags each item. You search by meaning, not keywords. Content goes in as text, PDF, HTML, Office documents, audio, or images; what comes back is a summary with tags and semantic neighbors. Audio and image files auto-extract metadata tags (artist, album, camera, date, etc.).\n\nWhat makes this more than a vector store: when you view your current context (`keep now`) or retrieve any item (`keep get`), keep automatically surfaces relevant open commitments, past learnings, and breakdowns — ranked by similarity and recency. The right things appear at the right time. That's what makes reflection real.\n\n- **Summarize, embed, tag** — URLs, files, and text are summarized and indexed on ingest\n- **Contextual feedback** — Open commitments and past learnings surface automatically\n- **Semantic search** — Find by meaning, not keywords\n- **Tag organization** — Speech acts, status, project, topic, type — structured and queryable\n- **Parts** — `analyze` decomposes documents into searchable sections, each with its own embedding and tags\n- **Strings** — Every note is a string of versions; reorganize history by meaning with `keep move`\n- **Works offline** — Local models (MLX, Ollama), or API providers (OpenAI, Gemini, Voyage, Anthropic)\n\nBacked by ChromaDB for vectors, SQLite for metadata and versions.\n\n> **[keepnotes.ai](https://keepnotes.ai)** — Hosted service. No local setup, no API keys to manage. Same SDK, managed infrastructure.\n\n### The Practice\n\nkeep is designed as a skill for AI agents — a practice, not just a tool. The [skill instructions](SKILL.md) teach agents to reflect before, during, and after action: check intentions, recognize commitments, capture learnings, notice breakdowns. `keep reflect` guides a structured reflection; `keep now` tracks current intentions and surfaces what's relevant.\n\nThis works because the tool and the skill reinforce each other. The tool stores and retrieves; the skill says *when* and *why*. An agent that uses both develops *skillful action* across sessions — not just recall, but looking before acting, and a deep review of outcomes afterwards.\n\n> Why build memory for AI agents? What does \"reflective practice\" mean here? I wrote a story: **[Wisdom, or Prompt-Engineering?](https://inguz.substack.com/p/keep)**\n\n### Integration\n\nThe skill instructions and hooks install into your agent's configuration automatically on first use (Claude Code, Kiro, OpenAI Codex, OpenClaw). Hooks inject `keep now` context at session start, on each prompt, and at session end — so the agent always knows its current intentions.\n\n| Layer | What it does |\n|-------|-------------|\n| **Skill prompt** | Always in system prompt — guides reflection, breakdown capture, document indexing |\n| **Hooks** | Inject `keep now -n 10` context at session start, prompt submit, and session end |\n| **Daily cron** | Scheduled deep reflection in an isolated session ([OpenClaw cron](SKILL.md#openclaw-integration)) |\n\nThe CLI alone is enough to start. The hooks make it automatic.\n\n---\n\n## Installation\n\n**Python 3.11–3.13 required.** Use [uv](https://docs.astral.sh/uv/) (recommended) or pip:\n\n```bash\nuv tool install keep-skill\n```\n\n**Hosted** (simplest — no local setup needed):\n```bash\nexport KEEPNOTES_API_KEY=...   # Sign up at https://keepnotes.ai\n```\n\n**Self-hosted** with API providers:\n```bash\nexport OPENAI_API_KEY=...      # Simplest (handles both embeddings + summarization)\n# Or: GEMINI_API_KEY=...       # Also does both\n# Or: VOYAGE_API_KEY=... and ANTHROPIC_API_KEY=...  # Separate services\n```\n\n**Local** (offline, no API keys): If [Ollama](https://ollama.com/) is running, keep auto-detects it. Or on macOS Apple Silicon: `uv tool install 'keep-skill[local]'`\n\nSee [docs/QUICKSTART.md](docs/QUICKSTART.md) for all provider options.\n\n---\n\n## Quick Start\n\n```bash\n# Index URLs, files, and notes (store auto-initializes on first use)\nkeep put https://inguz.substack.com/p/keep -t topic=practice\nkeep put \"file://$(keep config tool)/docs/library/han_verse.txt\" -t type=teaching\nkeep put \"Token refresh needs clock sync\" -t topic=auth\n\n# Search\nkeep find \"authentication flow\" --limit 5\nkeep find \"auth\" --since P7D           # Last 7 days\n\n# Retrieve\nkeep get file:///path/to/doc.md\nkeep get ID -V 1                       # Previous version\nkeep get \"ID@V{1}\"                     # Same as -V 1 (version identifier)\nkeep get ID --history                  # All versions\n\n# Tags\nkeep list --tag project=myapp          # Find by tag\nkeep find \"auth\" -t topic=auth         # Cross-project topic search\nkeep list --tags=                      # List all tag keys\n\n# Current intentions\nkeep now                               # Show what you're working on\nkeep now \"Fixing login bug\"            # Update intentions\n```\n\n### Python API\n\n```python\nfrom keep import Keeper\n\nkp = Keeper()\n\n# Index\nkp.put(uri=\"file:///path/to/doc.md\", tags={\"project\": \"myapp\"})\nkp.put(\"Rate limit is 100 req/min\", tags={\"topic\": \"api\"})\n\n# Search\nresults = kp.find(\"rate limit\", limit=5)\nfor r in results:\n    print(f\"[{r.score:.2f}] {r.summary}\")\n\n# Version history\nprev = kp.get_version(\"doc:1\", offset=1)\nversions = kp.list_versions(\"doc:1\")\n```\n\nSee [docs/QUICKSTART.md](docs/QUICKSTART.md) for configuration and more examples.\n\n---\n\n## Documentation\n\n- **[docs/QUICKSTART.md](docs/QUICKSTART.md)** — Setup, configuration, async summarization\n- **[docs/REFERENCE.md](docs/REFERENCE.md)** — Quick reference index\n- **[docs/TAGGING.md](docs/TAGGING.md)** — Tags, speech acts, project/topic organization\n- **[docs/VERSIONING.md](docs/VERSIONING.md)** — Document versioning and history\n- **[docs/META-DOCS.md](docs/META-DOCS.md)** — How meta-docs surface contextual feedback\n- **[docs/AGENT-GUIDE.md](docs/AGENT-GUIDE.md)** — Working session patterns\n- **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** — How it works under the hood\n- **[SKILL.md](SKILL.md)** — The reflective practice (for AI agents)\n\n---\n\n## License\n\nMIT\n\n---\n\n## Contributing\n\nPublished on [PyPI as `keep-skill`](https://pypi.org/project/keep-skill/).\n\nIssues and PRs welcome:\n- Provider implementations\n- Performance improvements\n- Documentation clarity\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\nFile v0.43.5:_meta.json\n\n{\n  \"ownerId\": \"kn72wa47ddf3nr5g4kv7xgt27s8092gt\",\n  \"slug\": \"keep\",\n  \"version\": \"0.43.5\",\n  \"publishedAt\": 1771246153290\n}\n\nFile v0.43.5:commands/reflect.md\n\n---\ndescription: Reflect on current actions, commitments, and intentions\n---\n\n# Reflect\n\nWhat is a mirror for? For reflection.\n\nActions — what you have done, what you are doing, what you intend to do — are to be reflected upon. This command is the practice.\n\n## 1. Gather\n\nSee what is, before analyzing.\n\n```bash\nkeep now\nkeep list --since P1D # or search, filter by tag, get context\n```\n\nRead the current intentions. Review what has been done since the last reflection. Note what you see.\n\n**Index important documents.** Before analyzing, capture any documents (URLs, files, references) encountered since the last reflection that are important to the user or task:\n```bash\nkeep put \"https://docs.example.com/api\" -t topic=integration -t project=current\nkeep put \"file:///path/to/design.pdf\" -t type=reference\n```\n\nWhat is this document? Why is it important to this work? Tag appropriately. This creates navigable knowledge for future sessions.\n\n## 2. The Mirror\n\nFor each significant action taken since the last reflection, ask:\n\n*Did this action lead to self-harm, to the harming others, or to both? Was it unskillful — with painful consequences, painful results?*\n\n- If unskillful: name it honestly. What assumption was wrong? What should be done differently? Capture the breakdown:\n  ```bash\n  keep put \"Assumed X, actually Y. Next time: Z\" -t type=breakdown\n  ```\n\n- If skillful: stay refreshed and joyful. What made it work? Continue training.\n\nDo not skip this step. Do not produce the appearance of reflection without actually reflecting.\n\n## 3. The Conversation\n\nWork is commitment management. Recognize the structure of what is happening.\n\n**What kind of conversation is active?**\n- **Action**: Commitments are being made. Request → Promise → Perform → Declare Complete → Declare Satisfied. *Satisfaction* — not completion — closes the loop. Who declares satisfaction here?\n- **Possibility**: Options are being explored. Hold lightly. Nothing is promised. Should fail if no actionable commitments emerge.\n- **Clarification**: Interpretations are being resolved. What might be misunderstood about conditions of satisfaction?\n- **Orientation**: Shared background is being established for future work.\n\n**Where are we in the commitment loop?**\n- What has been requested? What has been promised?\n- What conditions of satisfaction were established?\n- Are there open commitments — unfulfilled promises, unacknowledged completions?\n\n**Standing commitments.** Search keep for ongoing promises and recurring patterns:\n```bash\nkeep find \"commitment\" --since P30D\nkeep find \"pattern\" -t type=pattern\nkeep find \"always\" -t act=commitment\nkeep list -t act=commitment -t status=open\nkeep list -t act=request -t status=open\n```\nThese are the \"as always, please...\" requests — promises that persist across sessions. Are they being honored?\n\n**Moods.** A person's mood is driven by their vision of the future. What mood is present in this work? Ambition, serenity, acceptance, and respect serve. Anxiety, resentment, and resignation undermine. To shift a mood, create a different understanding about the future.\n\n**Assessments vs. assertions.** Am I stating facts (assertions) or making evaluations (assessments)? Are my assessments grounded — based on observable evidence? Ungrounded assessments distort action.\n\n**Breakdowns.** Where has the normal flow been interrupted? Breakdowns are valuable — they reveal assumptions that were invisible. Name them.\n\n**Trust.** Both unfulfilled promises and unnecessary requests destroy trust. Are there either?\n\n## 4. Ownership\n\n*I am the owner of my deeds and heir to my deeds. Deeds are my womb, my relative, and my refuge. I shall be the heir of whatever deeds I do, whether good or bad.*\n\n- What patterns are forming through these actions?\n- What should I exercise restraint about going forward?\n\n## 5. Update\n\nBased on the reflection, update what needs updating.\n\nIf intentions have changed:\n```bash\nkeep now \"Updated intentions based on reflection\" # -t to apply tags appropriate to the situation\n```\n\nIf there are learnings to capture:\n```bash\nkeep put \"What I learned\" -t type=learning\n```\n\nIf conversation patterns were recognized:\n```bash\nkeep put \"Pattern observed\" -t type=conversation_pattern\n```\n\nIf commitments need tracking:\n```bash\nkeep put \"I'll address the performance issue next session\" -t act=commitment -t status=open\n```\n\nIf a thread of work is complete, or the conversation is pivoting to a new topic, move the history:\n```bash\nkeep move \"thread-name\" -t project=myapp     # Archive and make room for what's next\n```\n\nPresent a brief summary of the reflection to the user. The value is in the reflection itself, not in lengthy output.\n\nFile v0.43.5:CONTRIBUTING.md\n\n# Contributing to keep-skill\n\nThis project is published on [PyPI as `keep-skill`](https://pypi.org/project/keep-skill/). Contributions are welcome under the MIT license.\n\n## How to Contribute\n\n- **Found a bug or have a feature idea?** Open an issue on GitHub\n- **Want to fix something?** Check the open issues, or submit a fix directly\n- **Making changes:** Fork the repo, create a feature branch, and open a pull request against `main`\n\nAll contributions appreciated!\n\n## Versioning\n\nWe use [semantic versioning](https://semver.org/):\n\n- **MAJOR** (1.0.0 → 2.0.0): Breaking changes to the public API\n- **MINOR** (0.1.0 → 0.2.0): New features, backward compatible\n- **PATCH** (0.1.0 → 0.1.1): Bug fixes, backward compatible\n\n**Current status:** Pre-1.0 (0.x.y), so minor versions may include breaking changes, but we try to avoid them.\n\nVersion is defined in four places (keep in sync):\n- `pyproject.toml` → `version = \"x.y.z\"`\n- `keep/__init__.py` → `__version__ = \"x.y.z\"`\n- `SKILL.md` frontmatter → `version: x.y.z`\n- `.claude-plugin/plugin.json` → `\"version\": \"x.y.z\"`\n\n## Public API\n\nThe following are considered public API — changes require version bumps and deprecation consideration:\n\n**Python API:**\n- `Keeper` class and its public methods\n- `Item` type and its fields\n- Anything exported in `keep/__init__.py`\n\n**CLI:**\n- All commands (`keep find`, `keep put`, `keep get`, etc.)\n- Command-line argument names and behavior\n\n**Not public API** (can change without notice):\n- Internal modules (`store.py`, `chunking.py`, `indexing.py`, etc.)\n- Provider implementations\n- Configuration file format (may evolve)\n\n## Backward Compatibility Guidelines\n\nWhen making changes:\n\n1. **Don't remove or rename public methods** — deprecate first, remove in next major version\n2. **Don't change method signatures** — add new optional parameters with defaults\n3. **Don't change return types** — extend, don't replace\n4. **CLI changes** — keep old flags working, add new ones\n\nIf you must break compatibility:\n- Document in commit message and changelog\n- Bump version appropriately\n- Provide migration guidance\n\n## Releases\n\nReleases are managed by the maintainer. To prepare a release:\n\n```bash\n# 1. Update version in all three places\n# pyproject.toml: version = \"x.y.z\"\n# keep/__init__.py: __version__ = \"x.y.z\"\n# SKILL.md frontmatter: version: x.y.z\n\n# 2. Commit\ngit add -A && git commit -m \"Release x.y.z\"\ngit tag vx.y.z\ngit push origin main --tags\n\n# 3. Build and publish (from machine with PyPI credentials)\nrm -rf dist/ build/\npython -m build\ntwine check dist/*\ntwine upload dist/*\n```\n\n## Questions?\n\nOpen an issue or reach out to the maintainer.\n\nFile v0.43.5:docs/AGENT-GUIDE.md\n\n# Reflective Memory — Agent Guide\n\nPatterns for using the reflective memory store effectively in working sessions.\n\nFor the practice (why and when), see [../SKILL.md](../SKILL.md).\nFor CLI reference, see [REFERENCE.md](REFERENCE.md). Be sure you understand the [output format](OUTPUT.md) — every item surfaces similar items and meta sections you can navigate with `keep get`.\n\n---\n\n## The Practice\n\nThis guide assumes familiarity with the reflective practice in [SKILL.md](../SKILL.md). The key points:\n\n**Reflect before acting:** Check your current work context and intentions.\n- What kind of conversation is this? (Action? Possibility? Clarification?)\n- What do I already know?\n```bash\nkeep now                    # Current intentions\nkeep find \"this situation\"  # Prior knowledge\n```\n\n**While acting:** Is this leading to harm? If yes: give it up.\n\n**Reflect after acting:** What happened? What did I learn?\n```bash\nkeep put \"what I learned\" -t type=learning\n```\n\n**Periodically:** Run a full structured reflection:\n```bash\nkeep reflect\n```\n\nThis cycle — reflect, act, reflect — is the mirror teaching. Memory isn't storage; it's how you develop skillful judgment.\n\n---\n\n## Working Session Pattern\n\nUse the nowdoc as a scratchpad to track where you are in the work. This isn't enforced structure — it's a convention that helps you (and future agents) maintain perspective.\n\n```bash\n# 1. Starting work — check context and intentions\nkeep now                                    # What am I working on?\n\n# 2. Update context as work evolves (tag by project and topic)\nkeep now \"Diagnosing flaky test in auth module\" -t project=myapp -t topic=testing\nkeep now \"Found timing issue\" -t project=myapp\n\n# 3. Check previous context if needed\nkeep now -V 1                               # Previous version\nkeep now --history                          # List all versions\nkeep now -t project=myapp                   # Find recent now with project tag\n\n# 4. Record learnings (cross-project knowledge uses topic only)\nkeep put \"Flaky timing fix: mock time instead of real assertions\" -t topic=testing -t type=learning\n```\n\n**Key insight:** The store remembers across sessions; working memory doesn't. When you resume, read context first. All updates create version history automatically.\n\n---\n\n## Agent Handoff\n\n**Starting a session:**\n```bash\nkeep now                              # Current intentions with version history\nkeep now --history                    # How intentions evolved\nkeep find \"recent work\" --since P1D   # Last 24 hours\n```\n\n**Ending a session:**\n```bash\nkeep now \"Completed OAuth2 flow. Token refresh working. Next: add tests.\" -t topic=auth\nkeep move \"auth-string\" -t project=myapp  # Archive this string of work\n```\n\n---\n\n## Strings\n\nAs you work, `keep now` accumulates a string of versions — a trace of how intentions evolved. `keep move` lets you name and archive that string, making room for what's next. It requires `-t` (tag filter) or `--only` (tip only) to prevent accidental grab-all moves.\n\n**Snapshot before pivoting.** When the conversation shifts topic, move what you have so far before moving on:\n```bash\nkeep move \"auth-string\" -t project=myapp     # Archive the auth string\nkeep now \"Starting on database migration\"    # Fresh context for new work\n```\n\n**Incremental archival.** Move to the same name repeatedly — versions append, building a running log across sessions:\n```bash\n# Session 1\nkeep move \"design-log\" -t project=myapp\n# Session 2 (more work on same project)\nkeep move \"design-log\" -t project=myapp      # Appends new versions\n```\n\n**End-of-session archive.** When a string of work is complete:\n```bash\nkeep move \"auth-string\" -t project=myapp\n```\n\n**Tag-filtered extraction.** When a session mixes multiple projects, extract just the string you want:\n```bash\nkeep move \"frontend-work\" -t project=frontend   # Leaves backend versions in now\n```\n\nThe moved item is a full versioned document — browse with `keep get name --history`, navigate with `-V 1`, `-V 2`, etc.\n\n---\n\n## Index Important Documents\n\nWhenever you encounter documents important to the task, index them:\n\n```bash\nkeep put \"https://docs.example.com/auth\" -t topic=auth -t project=myapp\nkeep put \"file:///path/to/design.pdf\" -t type=reference -t topic=architecture\n```\n\nAsk: what is this? Why is it important? Tag appropriately. Documents indexed during work become navigable knowledge.\n\n---\n\n## Breakdowns as Learning\n\nWhen the normal flow is interrupted — expected response doesn't come, ambiguity surfaces — an assumption has been revealed. **First:** complete the immediate conversation. **Then record:**\n\n```bash\nkeep put \"Assumed user wanted full rewrite. Actually: minimal patch.\" -t type=breakdown\n```\n\nBreakdowns are how agents learn.\n\n---\n\n## Tracking Commitments\n\nUse speech-act tags to make the commitment structure of work visible:\n\n```bash\n# Track promises\nkeep put \"I'll fix the auth bug\" -t act=commitment -t status=open -t project=myapp\n\n# Track requests\nkeep put \"Please review the PR\" -t act=request -t status=open\n\n# Query open work\nkeep list -t act=commitment -t status=open\n\n# Close the loop\nkeep tag-update ID --tag status=fulfilled\n```\n\nSee [TAGGING.md](TAGGING.md#speech-act-tags) for the full speech-act framework.\n\n---\n\n## Data Model\n\nAn item has:\n- A unique identifier (URI, content hash, or system ID)\n- Timestamps (`_created`, `_updated`)\n- A summary of the content\n- Tags (`{key: value, ...}`)\n- Version history (previous versions archived automatically)\n\nThe full original document is not stored. Summaries are contextual — tags shape how new items are understood. See [KEEP-PUT.md](KEEP-PUT.md#contextual-summarization).\n\n---\n\n## System Documents\n\nBundled system docs provide patterns and conventions, accessible via `keep get`:\n\n| ID | What it provides |\n|----|------------------|\n| `.domains` | Domain-specific organization patterns |\n| `.conversations` | Conversation framework (action, possibility, clarification) |\n| `.tag/act` | Speech-act categories |\n| `.tag/status` | Lifecycle states |\n| `.tag/project` | Project tag conventions |\n| `.tag/topic` | Topic tag conventions |\n\n---\n\n## See Also\n\n- [REFERENCE.md](REFERENCE.md) — Quick reference index\n- [OUTPUT.md](OUTPUT.md) — How to read the frontmatter output\n- [TAGGING.md](TAGGING.md) — Tags, speech acts, project/topic\n- [VERSIONING.md](VERSIONING.md) — Document versioning\n- [QUICKSTART.md](QUICKSTART.md) — Installation and setup\n\nFile v0.43.5:docs/ARCHITECTURE.md\n\n# Architecture Overview\n\n## What is keep?\n\n**keep** is a reflective memory system providing persistent storage with vector similarity search. It's designed as an agent skill for OpenClaw and other agentic environments, enabling agents to remember information across sessions over time.\n\nThink of it as: **ChromaDB + embeddings + summarization + tagging** wrapped in a simple API.\n\nPublished by Hugh Pyle, \"inguz ᛜ outcomes\", under the MIT license.\nContributions are welcome; code is conversation, \"right speech\" is encouraged.\n\n---\n\n## Core Concept\n\nEvery stored item has:\n- **ID**: URI or custom identifier\n- **Summary**: Human-readable text (stored, searchable)\n- **Embedding**: Vector representation (for semantic search)\n- **Tags**: Key-value metadata (for filtering)\n- **Timestamps**: Created/updated (auto-managed)\n- **Version History**: Previous versions archived automatically on update\n\nThe original document content is **not stored** — only the summary and embedding.\n\n---\n\n## Architecture\n\n```\n┌─────────────────────────────────────────────────────────────┐\n│  API Layer (api.py)                                         │\n│  - Keeper class                                             │\n│  - High-level operations: put(), find(), get()              │\n│  - Version management: get_version(), list_versions()       │\n└──────────────────┬──────────────────────────────────────────┘\n                   │\n        ┌──────────┼──────────┬──────────┬──────────┬───────────┐\n        │          │          │          │          │           │\n        ▼          ▼          ▼          ▼          ▼           ▼\n   ┌────────┐ ┌─────────┐ ┌────────┐ ┌────────┐ ┌─────────┐ ┌─────────┐\n   │Document│ │Embedding│ │Summary │ │Media   │ │Vector   │ │Document │\n   │Provider│ │Provider │ │Provider│ │Descr.* │ │Store    │ │Store    │\n   └────────┘ └─────────┘ └────────┘ └────────┘ └─────────┘ └─────────┘\n       │          │           │          │             │           │\n   fetch()    embed()    summarize()  describe()  vectors/    summaries/\n   from URI   text→vec  text→summary  media→text  search      versions\n```\n\n### Components\n\n**[api.py](keep/api.py)** — Main facade\n- `Keeper` class\n- Coordinates providers and store\n- Implements query operations with recency decay\n\n**[store.py](keep/store.py)** — Vector persistence\n- `ChromaStore` wraps ChromaDB\n- Handles vector storage, similarity search, metadata queries\n- Versioned embeddings: `{id}@v{version}` for history\n\n**[document_store.py](keep/document_store.py)** — Document persistence\n- `DocumentStore` wraps SQLite\n- Stores summaries, tags, timestamps\n- Version history: archives previous versions on update\n\n**[providers/](keep/providers/)** — Pluggable services\n- **Document**: Fetch content from URIs (file://, https://)\n- **Embedding**: Generate vectors (sentence-transformers, OpenAI, Ollama, MLX)\n- **Summarization**: Generate summaries (truncate, LLM-based)\n- **Registry**: Factory for lazy-loading providers\n\n**[config.py](keep/config.py)** — Configuration\n- Detects available providers (platform, API keys, Ollama)\n- Persists choices in `keep.toml`\n- Auto-creates on first use\n\n**[types.py](keep/types.py)** — Data model\n- `Item`: Immutable result type\n- System tag protection (prefix: `_`)\n\n---\n\n## Data Flow\n\n### Indexing: put(uri=...) or put(content)\n\n```\nURI or content\n    │\n    ▼\n┌─────────────────┐\n│ Fetch/Use input │ ← DocumentProvider (for URIs only)\n└────────┬────────┘\n         │ raw bytes\n         ▼\n┌─────────────────┐\n│ Content Regular-│ ← Extract text from HTML/PDF\n│ ization         │   (scripts/styles removed)\n└────────┬────────┘\n         │ clean text\n         ▼\n┌─────────────────┐\n│ Media Enrichment│ ← Optional: vision description (images)\n│ (if configured) │   or transcription (audio) appended\n└────────┬────────┘\n         │ enriched text\n    ┌────┴────┬─────────────┐\n    │         │             │\n    ▼         ▼             ▼\n  embed()  summarize()   tags (from args)\n    │         │             │\n    └────┬────┴─────────────┘\n         │\n    ┌────┴────────────────┐\n    │                     │\n    ▼                     ▼\n┌─────────────────┐  ┌─────────────────┐\n│ DocumentStore   │  │ ChromaStore     │\n│ upsert()        │  │ upsert()        │\n│ - summary       │  │ - embedding     │\n│ - tags          │  │ - summary       │\n│ - timestamps    │  │ - tags          │\n│ - archive prev  │  │ - version embed │\n└─────────────────┘  └─────────────────┘\n```\n\n**Versioning on update:**\n- DocumentStore archives current version before updating\n- ChromaStore adds versioned embedding (`{id}@v{N}`) if content changed\n- Same content (hash match) skips duplicate embedding\n\n### Retrieval: find(query)\n\n```\nquery text\n    │\n    ▼\n  embed()  ← EmbeddingProvider\n    │\n    │ query vector\n    ▼\n┌───────────────────┐\n│ ChromaStore       │\n│ query_embedding() │ ← L2 distance search\n└─────────┬─────────┘\n          │\n          ▼ results with distance scores\n    ┌──────────────┐\n    │ Apply decay  │ ← Recency weighting (ACT-R style)\n    │ score × 0.5^(days/half_life)\n    └──────┬───────┘\n           │\n           ▼\n    list[Item] (sorted by effective score)\n```\n\n### Delete / Revert: delete(id) or revert(id)\n\n```\ndelete(id)\n    │\n    ▼\n  version_count(id)\n    │\n    ├── 0 versions → full delete from both stores\n    │\n    └── N versions → revert to previous\n            │\n            ├─ get archived embedding from ChromaDB (id@vN)\n            ├─ restore_latest_version() in DocumentStore\n            │    (promote latest version row to current, delete version row)\n            ├─ upsert restored embedding as current in ChromaDB\n            └─ delete versioned entry (id@vN) from ChromaDB\n```\n\n---\n\n## Key Design Decisions\n\n**1. Schema as Data**\n- System configuration stored as documents in the store\n- Enables agents to query and update behavior\n- (Not yet implemented: routing, guidance documents)\n\n**2. Lazy Provider Loading**\n- Providers registered at first use, not import time\n- Avoids crashes when optional dependencies missing\n- Better error messages about what's needed\n\n**3. Separation of Concerns**\n- Store is provider-agnostic (only knows about vectors/metadata)\n- Providers are store-agnostic (only know about text→vectors)\n- Easy to swap implementations\n\n**4. No Original Content Storage**\n- Reduces storage size\n- Forces meaningful summarization\n- URIs can be re-fetched if needed\n\n**5. Immutable Items**\n- `Item` is frozen dataclass\n- Updates via `put()` return new Item\n- Prevents accidental mutation bugs\n\n**6. System Tag Protection**\n- Tags prefixed with `_` are system-managed\n- Source tags filtered before storage\n- Prevents user override of timestamps, etc.\n\n**7. Document Versioning**\n- All documents retain history automatically on update\n- Previous versions archived in SQLite `document_versions` table\n- Content-addressed IDs for text updates enable versioning via tag changes\n- Embeddings stored for all versions (enables temporal search)\n- No auto-pruning: history preserved indefinitely\n\n**8. Version-Based Addressing**\n- Versions addressed by offset from current: 0=current, 1=previous, 2=two ago\n- CLI uses `@V{N}` syntax for shell composition: `keep get \"doc:1@V{1}\"`\n- Display format (v0, v1, v2) matches retrieval offset (`-V 0`, `-V 1`, `-V 2`)\n- Offset computation assumes `list_versions()` returns newest-first ordering\n- Security: literal ID lookup before `@V{N}` parsing prevents confusion attacks\n\n---\n\n## Storage Layout\n\n```\nstore_path/\n├── keep.toml               # Provider configuration\n├── chroma/                 # ChromaDB persistence (vectors + metadata)\n│   └── [collection]/       # One collection = one namespace\n│       ├── embeddings\n│       ├── metadata\n│       └── documents\n├── document_store.db       # SQLite store (summaries, tags, versions)\n│   ├── documents           # Current version of each document\n│   └── document_versions   # Archived previous versions\n└── embedding_cache.db      # SQLite cache for embeddings\n```\n\n---\n\n## Provider Types\n\n### Embedding Providers\nGenerate vector representations for semantic search.\n\n- **voyage**: API-based, Anthropic's recommended partner (VOYAGE_API_KEY)\n- **openai**: API-based, high quality (OPENAI_API_KEY)\n- **gemini**: API-based, Google (GEMINI_API_KEY or GOOGLE_CLOUD_PROJECT for Vertex AI)\n- **ollama**: Local server, auto-detected, any model (OLLAMA_HOST)\n- **sentence-transformers**: Local, CPU/GPU, no API key\n- **MLX**: Apple Silicon optimized, local, no API key\n\nDimension determined by model. Must be consistent across indexing and queries.\n\n### Summarization Providers\nGenerate human-readable summaries from content.\n\n- **anthropic**: LLM-based, cost-effective option (ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN)\n- **openai**: LLM-based, high quality (OPENAI_API_KEY)\n- **gemini**: LLM-based, Google (GEMINI_API_KEY or GOOGLE_CLOUD_PROJECT for Vertex AI)\n- **ollama**: LLM-based, local server, auto-detected (OLLAMA_HOST)\n- **MLX**: LLM-based, local, no API key\n- **truncate**: Simple text truncation (fallback)\n- **passthrough**: Store content as-is (with length limit)\n\n**Contextual Summarization:**\n\nWhen documents have user tags (domain, topic, project, etc.), the summarizer\nreceives context from related items. This produces summaries that highlight\nrelevance to the tagged context rather than generic descriptions.\n\nHow it works:\n1. When processing pending summaries, the system checks for user tags\n2. Finds similar items that share any of those tags (OR-union)\n3. Boosts scores for items sharing multiple tags (+20% per additional match)\n4. Top 5 related summaries are passed as context to the LLM\n5. The summary reflects what's relevant to that context\n\nExample: Indexing a medieval text with `domain=practice` produces a summary\nhighlighting its relevance to contemplative practice, not just \"a 13th-century\nguide for anchoresses.\"\n\n**Tag changes trigger re-summarization:** When user tags are added, removed, or\nchanged on an existing document, it's re-queued for contextual summarization\neven if content is unchanged. The existing summary is preserved until the new\none is ready.\n\nNon-LLM providers (truncate, first_paragraph, passthrough) ignore context.\n\n### Document Providers\nFetch content from URIs with content regularization.\n\n- **composite**: Handles file://, https:// (default)\n- Extensible for s3://, gs://, etc.\n\n**Content Regularization:**\n- **PDF**: text extracted via pypdf\n- **HTML**: text extracted via BeautifulSoup (scripts/styles removed)\n- **DOCX/PPTX**: text + tables/slides extracted via python-docx/python-pptx; auto-tags: author, title\n- **Audio** (MP3, FLAC, OGG, WAV, AIFF, M4A, WMA): metadata via tinytag; auto-tags: artist, album, genre, year\n- **Images** (JPEG, PNG, TIFF, WEBP): EXIF metadata via Pillow; auto-tags: dimensions, camera, date\n- **Other formats**: treated as plain text\n\nProvider-extracted tags merge with user tags (user wins on collision). This ensures both embedding and summarization receive clean text.\n\n### Media Description Providers (optional)\nGenerate text descriptions from media files, enriching metadata-only content.\n\n- **mlx**: Apple Silicon — vision (mlx-vlm) + audio transcription (mlx-whisper)\n- **ollama**: Local server — vision models only (llava, moondream, bakllava)\n\nMedia description runs in `Keeper.put()` between fetch and upsert. Descriptions are appended to the metadata content before embedding/summarization, making media files semantically searchable by their visual or audio content.\n\nDesign points:\n- Only triggered for non-text content types (image/*, audio/*)\n- Lazy sub-provider loading: MLX composite only loads VLM for first image, whisper for first audio\n- GPU-locked via `LockedMediaDescriber` (same file-lock pattern as summarization)\n- Graceful degradation: errors never block indexing; no provider = metadata-only (unchanged behavior)\n- Optional dependency: `pip install keep-skill[media]` for MLX models\n\n---\n\n## Extension Points\n\n**New Provider**\n1. Implement Protocol from [providers/base.py](keep/providers/base.py)\n2. Register with `get_registry().register_X(\"name\", YourClass)`\n3. Reference by name in config\n\n**New Store Backend**\n- Current: ChromaDB\n- Future: Could extract Protocol from `ChromaStore`\n- Candidates: PostgreSQL+pgvector, SQLite+faiss\n\n**New Query Types**\n- Add methods to `Keeper`\n- Delegate to `ChromaStore` or implement in API layer\n\n---\n\n## Performance Characteristics\n\n**Indexing**\n- Embedding: ~50-200ms per item (local models)\n- Summarization: ~100ms-2s per item (depends on provider)\n- Storage: ~10ms per item\n\n**Querying**\n- Semantic search: ~10-50ms for 10k items\n- Tag queries: ~1-10ms\n- Full-text search: ~10-100ms\n\n**Caching**\n- Embedding cache avoids re-computing for repeated queries\n- Persists across sessions in SQLite\n\n**Scaling**\n- ChromaDB handles ~100k items comfortably\n- Larger datasets may benefit from PostgreSQL backend\n- Embedding dimension affects memory (384d vs 1536d)\n\n---\n\n## Failure Modes\n\n**Missing Dependencies**\n- Registry provides clear error about which provider failed\n- Lists available alternatives\n- Lazy loading prevents import-time crashes\n\n**URI Fetch Failures**\n- `put()` raises `IOError` for unreachable URIs\n- Original error preserved in exception chain\n\n**Invalid Config**\n- Config auto-created with detected defaults\n- Validation on load with clear error messages\n\n**Store Inconsistency**\n- On startup, a background thread checks for mismatches between ChromaDB and SQLite\n- Missing search index entries or orphaned vectors are reconciled automatically\n- This runs as a daemon thread and does not block normal operation\n\n**Store Corruption**\n- ChromaDB is resilient (SQLite-backed)\n- Embedding cache can be deleted and rebuilt\n- No critical data loss if store is backed up\n\n---\n\n## Testing Strategy\n\n**Unit Tests**: [tests/test_core.py](tests/test_core.py)\n- Data types (Item, filtering)\n- Context dataclasses\n- No external dependencies\n\n**Document Store Tests**: [tests/test_document_store.py](tests/test_document_store.py)\n- SQLite persistence\n- Version history (archive, retrieval, navigation)\n- Schema migration\n\n**Integration Tests**: [tests/test_integration.py](tests/test_integration.py)\n- End-to-end: remember → find\n- Multiple collections\n- Recency decay\n- Embedding cache\n\n**Provider Tests**: (TODO)\n- Each provider independently\n- Graceful degradation when unavailable\n\n---\n\n## Future Work\n\n### Planned (in [later/](later/))\n- **Relationships**: Link items with typed edges\n- **Advanced Tagging**: LLM-based tag generation\n- **Hierarchical Context**: Topic summaries, working context\n\n### Under Consideration\n- Multi-store facade (private/shared routing)\n- Batch operations for performance\n- Incremental indexing (track changes)\n- Export/import for backup\n- Web UI for exploration\n\nFile v0.43.5:docs/KEEP-ANALYZE.md\n\n# keep analyze\n\nDecompose a note or string into meaningful parts.\n\n## Usage\n\n```bash\nkeep analyze ID                       # Analyze using configured provider\nkeep analyze ID -t topic -t type      # With guidance tags\n```\n\n## What it does\n\n`analyze` uses an LLM to decompose content into meaningful sections, each\nwith its own summary, tags, and embedding. This enables targeted search:\n`find` matches specific sections, not just whole documents.\n\nTwo modes, auto-detected:\n- **Documents** (URI sources): structural decomposition — chapters, topics,\n  headings, thematic units\n- **Strings** (inline notes with version history): episodic decomposition —\n  the version history is assembled chronologically and decomposed into\n  distinct phases, topic shifts, or narrative arcs\n\nParts are the structural counterpart to versions:\n- **Versions** (`@V{N}`) are temporal — each `put` adds one\n- **Parts** (`@P{N}`) are structural — each `analyze` replaces all parts\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `-t`, `--tag KEY` | Guidance tag keys (repeatable). Fetches `.tag/KEY` descriptions to guide decomposition |\n| `--foreground`, `--fg` | Run in foreground and wait for results (default: background) |\n| `--force` | Re-analyze even if parts are already current |\n| `-s`, `--store PATH` | Override store directory |\n\n## Background processing\n\nBy default, `analyze` runs in the background, serialized with other ML work\n(summarization, embedding). Use `--fg` to wait for results:\n\n```bash\nkeep analyze doc:1                    # Returns immediately, runs in background\nkeep analyze doc:1 --fg               # Waits for completion\n```\n\nBackground tasks are processed by the same queue as `process-pending` summaries.\n\n## Part addressing\n\nAppend `@P{N}` to any ID to access a specific part:\n\n```bash\nkeep get \"doc:1@P{1}\"           # Part 1\nkeep get \"doc:1@P{3}\"           # Part 3\n```\n\nParts include prev/next navigation:\n```yaml\n---\nid: doc:1@P{2}\ntags: {topic: analysis}\nprev:\n  - @P{1}\nnext:\n  - @P{3}\n---\nDetailed analysis of the main argument...\n```\n\n## Parts in get output\n\nWhen a document has parts, `keep get` shows a parts manifest:\n\n```yaml\n---\nid: doc:1\nsimilar:\n  - doc:2 (0.85) 2026-01-14 Related document...\nparts:\n  - @P{1} Introduction and overview of the topic\n  - @P{2} Detailed analysis of the main argument\n  - @P{3} Conclusions and future directions\nprev:\n  - @V{1} 2026-01-13 Previous summary...\n---\nDocument summary here...\n```\n\n## Parts in search results\n\nParts have their own embeddings and appear naturally in `find` results:\n\n```bash\nkeep find \"main argument\"\n# doc:1@P{2}  2026-01-14 Detailed analysis of the main argument...\n```\n\n## Smart skip\n\nAnalysis is expensive (LLM call per document). To avoid redundant work,\n`analyze` tracks a content hash at the time of analysis. If the document\nhasn't changed since the last analysis, the call is skipped:\n\n```bash\nkeep analyze doc:1                    # Analyzes, stores _analyzed_hash\nkeep analyze doc:1                    # Skipped — parts are current\nkeep put doc:1 \"updated content\"      # Content changes\nkeep analyze doc:1                    # Re-analyzes (content changed)\n```\n\nThis makes `put --analyze` safe for cron jobs — point it at a folder daily\nand only new or changed files get analyzed:\n\n```bash\nkeep put /path/to/docs/ --analyze     # Only analyzes what needs it\n```\n\nUse `--force` to override the skip:\n\n```bash\nkeep analyze doc:1 --force            # Re-analyze regardless\n```\n\n## Re-analysis\n\nRunning `analyze` on changed content (or with `--force`) replaces all\nprevious parts:\n\n```bash\nkeep analyze doc:1                    # Creates parts\nkeep analyze doc:1 -t topic --force   # Re-analyze with guidance — replaces all parts\n```\n\n## Guidance tags\n\nTag keys passed with `-t` fetch the corresponding `.tag/KEY` system documents\n(e.g., `.tag/topic`, `.tag/type`). These descriptions tell the LLM what each\ntag means and what values are appropriate, producing better decomposition and\nmore consistent tagging — even with smaller models.\n\n```bash\nkeep analyze doc:1 -t topic -t type   # Guided by tag descriptions\n```\n\n## Python API\n\n```python\nkp = Keeper()\n\n# Analyze (skips if parts are current)\nparts = kp.analyze(\"doc:1\")\nparts = kp.analyze(\"doc:1\", tags=[\"topic\", \"type\"])\nparts = kp.analyze(\"doc:1\", force=True)  # Override skip\n\n# Enqueue for background processing (returns False if skipped)\nenqueued = kp.enqueue_analyze(\"doc:1\")\nenqueued = kp.enqueue_analyze(\"doc:1\", force=True)\n\n# Access parts\npart = kp.get_part(\"doc:1\", 1)        # Returns Item\nparts = kp.list_parts(\"doc:1\")        # Returns list[PartInfo]\n```\n\n## See Also\n\n- [VERSIONING.md](VERSIONING.md) — Versions (temporal) vs parts (structural)\n- [KEEP-GET.md](KEEP-GET.md) — Retrieving items and parts\n- [KEEP-FIND.md](KEEP-FIND.md) — Search results include parts\n- [REFERENCE.md](REFERENCE.md) — Quick reference index\n\nFile v0.43.5:docs/KEEP-CONFIG.md\n\n# keep config\n\nShow configuration and resolve paths.\n\n## Usage\n\n```bash\nkeep config                           # Show all config\nkeep config file                      # Config file location\nkeep config tool                      # Package directory (SKILL.md location)\nkeep config docs                      # Documentation directory\nkeep config store                     # Store path\nkeep config openclaw-plugin           # OpenClaw plugin directory\nkeep config providers                 # All provider config\nkeep config providers.embedding       # Embedding provider name\n```\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `--reset-system-docs` | Force reload system documents from bundled content |\n| `-s`, `--store PATH` | Override store directory |\n\n## Config file location\n\nThe config file is `keep.toml` inside the config directory. The config directory is resolved in this order:\n\n1. **`KEEP_CONFIG` environment variable** — explicit path to config directory\n2. **Tree-walk** — search from current directory up to `~` for `.keep/keep.toml`\n3. **Default** — `~/.keep/`\n\nThe tree-walk enables project-local stores: place a `.keep/keep.toml` in your project root and `keep` will use it when you're in that directory tree.\n\n## Store path resolution\n\nThe store (where data lives) is resolved separately from config:\n\n1. **`--store` CLI option** — per-command override\n2. **`KEEP_STORE_PATH` environment variable**\n3. **`store.path` in config file** — `[store]` section of `keep.toml`\n4. **Config directory itself** — backwards compatibility default\n\n## Config file format\n\n```toml\n[store]\nversion = 2\nmax_summary_length = 1000\n\n[embedding]\nname = \"mlx\"                           # or \"voyage\", \"openai\", \"ollama\", \"sentence_transformers\"\nmodel = \"all-MiniLM-L6-v2\"\n\n[summarization]\nname = \"mlx\"                           # or \"anthropic\", \"openai\", \"ollama\"\nmodel = \"mlx-community/Llama-3.2-3B-Instruct-4bit\"\n\n[media]\nname = \"mlx\"                           # or \"ollama\" (auto-detected)\nvision_model = \"mlx-community/Qwen2-VL-2B-Instruct-4bit\"\nwhisper_model = \"mlx-community/whisper-large-v3-turbo\"\n\n[document]\nname = \"composite\"\n\n[tags]\nproject = \"my-project\"                 # Default tags applied to all new items\nowner = \"alice\"\n```\n\n## Environment variables\n\n```bash\nKEEP_STORE_PATH=/path/to/store        # Override store location\nKEEP_CONFIG=/path/to/.keep            # Override config directory\nKEEP_TAG_PROJECT=myapp                # Auto-apply tags (any KEEP_TAG_* variable)\nKEEP_VERBOSE=1                        # Debug logging to stderr\nKEEP_NO_SETUP=1                       # Skip auto-install of tool integrations\n```\n\n## Config subpaths\n\n| Path | Returns |\n|------|---------|\n| `file` | Config file path (`~/.keep/keep.toml`) |\n| `tool` | Package directory (where SKILL.md lives) |\n| `docs` | Documentation directory |\n| `store` | Store data path |\n| `openclaw-plugin` | OpenClaw plugin directory |\n| `providers` | All provider configuration |\n| `providers.embedding` | Embedding provider name |\n| `providers.summarization` | Summarization provider name |\n| `providers.media` | Media description provider name |\n\nSubpath output is raw (unquoted) for shell scripting:\n\n```bash\ncat \"$(keep config tool)/SKILL.md\"    # Read the practice guide\nls \"$(keep config store)\"             # List store contents\n```\n\n## Resetting system documents\n\nSystem documents (`.conversations`, `.domains`, `.tag/*`, etc.) are bundled with keep and loaded on first use. If they've been modified or corrupted:\n\n```bash\nkeep config --reset-system-docs       # Reload all from bundled content\n```\n\n## See Also\n\n- [QUICKSTART.md](QUICKSTART.md) — Installation and provider setup\n- [REFERENCE.md](REFERENCE.md) — Quick reference index\n\nFile v0.43.5:docs/KEEP-FIND.md\n\n# keep find\n\nFind items by semantic similarity or full-text search.\n\n## Usage\n\n```bash\nkeep find \"authentication\"            # Semantic similarity search\nkeep find \"auth\" --text               # Full-text search on summaries\nkeep find --id ID                     # Find items similar to an existing item\n```\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `--text` | Use full-text search instead of semantic similarity |\n| `--id ID` | Find items similar to this ID (instead of text query) |\n| `--include-self` | Include the queried item (only with `--id`) |\n| `-t`, `--tag KEY=VALUE` | Filter by tag (repeatable, AND logic) |\n| `-n`, `--limit N` | Maximum results (default 10) |\n| `--since DURATION` | Only items updated since (see time filtering below) |\n| `-H`, `--history` | Include archived versions of matching items |\n| `-a`, `--all` | Include hidden system notes (IDs starting with `.`) |\n| `-s`, `--store PATH` | Override store directory |\n\n## Semantic vs full-text search\n\n**Semantic search** (default) finds items by meaning using embeddings. \"authentication\" matches items about \"login\", \"OAuth\", \"credentials\" even if they don't contain the word \"authentication\".\n\n**Full-text search** (`--text`) matches exact words in summaries. Faster but literal.\n\n## Similar-to-item search\n\nFind items similar to an existing document:\n\n```bash\nkeep find --id file:///path/to/doc.md           # Similar to this document\nkeep find --id %a1b2c3d4                        # Similar to this item\nkeep find --id %a1b2c3d4 --since P30D           # Similar items from last 30 days\n```\n\n## Tag filtering\n\nCombine semantic search with tag filters (AND logic):\n\n```bash\nkeep find \"auth\" -t project=myapp               # Search within a project\nkeep find \"auth\" -t project -t topic=security    # Multiple tags (AND)\n```\n\n## Time filtering\n\nThe `--since` option accepts ISO 8601 durations or dates:\n\n```bash\nkeep find \"auth\" --since P7D           # Last 7 days\nkeep find \"auth\" --since P1W           # Last week\nkeep find \"auth\" --since PT1H          # Last hour\nkeep find \"auth\" --since P1DT12H       # 1 day 12 hours\nkeep find \"auth\" --since 2026-01-15    # Since specific date\n```\n\n## Including archived versions\n\n```bash\nkeep find \"auth\" --history             # Also search old versions of items\n```\n\n## See Also\n\n- [KEEP-LIST.md](KEEP-LIST.md) — List and filter by tags\n- [KEEP-GET.md](KEEP-GET.md) — Retrieve full item details\n- [TAGGING.md](TAGGING.md) — Tag filtering patterns\n- [REFERENCE.md](REFERENCE.md) — Quick reference index\n\nFile v0.43.5:docs/KEEP-GET.md\n\n# keep get\n\nRetrieve item(s) by ID.\n\n## Usage\n\n```bash\nkeep get ID                           # Current version with similar items\nkeep get ID1 ID2 ID3                  # Multiple items (separated by ---)\nkeep get ID -V 1                      # Previous version\nkeep get \"ID@V{1}\"                    # Same as -V 1 (version identifier syntax)\n```\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `-V`, `--version N` | Get specific version (0=current, 1=previous) |\n| `-H`, `--history` | List all versions (default 10, use `-n` to override) |\n| `-S`, `--similar` | List similar items (default 10) |\n| `-M`, `--meta` | List meta items |\n| `-R`, `--resolve QUERY` | Inline meta query (metadoc syntax, repeatable) |\n| `-P`, `--parts` | List structural parts (from `analyze`) |\n| `-t`, `--tag KEY=VALUE` | Require tag (error if item doesn't match) |\n| `-n`, `--limit N` | Max items for --history, --similar, --meta (default 10) |\n| `-s`, `--store PATH` | Override store directory |\n\n## Default output\n\nSingle-item commands (`get`, `now`) default to full YAML frontmatter format:\n\n```yaml\n---\nid: %a1b2c3d4\ntags: {project: myapp, topic: auth, type: learning}\nsimilar:\n  - %e5f6a7b8 (0.89) 2026-01-14 Related authentication...\n  - %c9d0e1f2 (0.85) 2026-01-13 Token handling notes...\nmeta/learnings:\n  - %d3e4f5a6 Token refresh needs clock sync\nprev:\n  - @V{1} 2026-01-14 Previous summary text...\n---\nDocument summary here...\n```\n\n## Multiple IDs\n\n```bash\nkeep get doc:1 doc:2 doc:3            # Items separated by ---\nkeep --ids list -n 5 | xargs keep get # Pipe from list\n```\n\n## Parts\n\nAccess structural parts produced by `keep analyze`:\n\n```bash\nkeep get \"ID@P{1}\"                    # Part 1 of a document\nkeep get \"ID@P{3}\"                    # Part 3\nkeep get ID --parts                   # List all parts\n```\n\nParts include prev/next navigation and part-specific similar items.\n\n## Display modes\n\n```bash\nkeep get ID --similar                 # Show similar items\nkeep get ID --similar -n 20           # Show 20 similar items\nkeep get ID --meta                    # Show meta items\nkeep get ID --meta -n 5              # Show 5 meta items per section\nkeep get ID --history                # List all versions\nkeep get ID --parts                  # List structural parts\n```\n\n## Tag filtering\n\n```bash\nkeep get ID -t project=myapp          # Error if item doesn't have this tag\n```\n\n## See Also\n\n- [VERSIONING.md](VERSIONING.md) — Version identifiers and history\n- [KEEP-FIND.md](KEEP-FIND.md) — Search for items by meaning\n- [META-DOCS.md](META-DOCS.md) — How meta sections work\n- [REFERENCE.md](REFERENCE.md) — Quick reference index\n\nFile v0.43.5:docs/KEEP-LIST.md\n\n# keep list\n\nList recent items, filter by tags, or list tag keys and values.\n\n## Usage\n\n```bash\nkeep list                             # Recent items (by update time)\nkeep list -n 20                       # Show 20 most recent\nkeep list --sort accessed             # Sort by last access time\n```\n\n## Options\n\n| Option | Description |\n|--------|-------------|\n| `-n`, `--limit N` | Maximum results (default 10) |\n| `-t`, `--tag KEY=VALUE` | Filter by tag (repeatable, AND logic) |\n| `-T`, `--tags=` | List all tag keys |\n| `-T`, `--tags=KEY` | List values for a specific tag key |\n| `--sort ORDER` | Sort by `updated` (default) or `accessed` |\n| `--since DURATION` | Only items updated since (ISO duration or date) |\n| `-H`, `--history` | Include archived versions |\n| `-P`, `--parts` | Include structural parts (from `analyze`) |\n| `-a`, `--all` | Include hidden system notes (IDs starting with `.`) |\n| `-s`, `--store PATH` | Override store directory |\n\n## Tag filtering\n\n```bash\nkeep list --tag project=myapp         # Items with project=myapp\nkeep list --tag project               # Items with any 'project' tag\nkeep list --tag foo --tag bar         # Items with both tags (AND)\nkeep list --tag project --since P7D   # Combine tag filter with recency\n```\n\n## Listing tags\n\nThe `--tags` option (note: different from `--tag`) lists tag metadata:\n\n```bash\nkeep list --tags=                     # List all distinct tag keys\nkeep list --tags=project              # List all values for 'project' tag\n```\n\n## Time filtering\n\n```bash\nkeep list --since P3D                 # Last \n\nArchive v0.38.4: 99 files, 385125 bytes\n\nFiles: .claude-plugin/plugin.json (186b), .claude/settings.json (529b), .github/workflows/test.yml (468b), commands/reflect.md (4720b), CONTRIBUTING.md (2671b), docs/AGENT-GUIDE.md (6463b), docs/ARCHITECTURE.md (16400b), docs/KEEP-CONFIG.md (3756b), docs/KEEP-FIND.md (2472b), docs/KEEP-GET.md (2149b), docs/KEEP-LIST.md (2128b), docs/KEEP-MOVE.md (4239b), docs/KEEP-NOW.md (2990b), docs/KEEP-PUT.md (4386b), docs/library/an5.57_translation-en-sujato.json (7443b), docs/library/fortytwo_chapters.txt (33053b), docs/library/han_verse.txt (3689b), docs/library/INDEX.md (7189b), docs/library/mn61.html (25229b), docs/library/mumford_sticks_and_stones.txt (264881b), docs/library/true_person_no_rank.md (7091b), docs/META-DOCS.md (6472b), docs/OPENCLAW-INTEGRATION.md (2395b), docs/OUTPUT.md (5264b), docs/PYTHON-API.md (7108b), docs/QUICKSTART.md (12393b), docs/REFERENCE.md (5907b), docs/RELEASING.md (1442b), docs/SYSTEM-TAGS.md (4974b), docs/TAGGING.md (5162b), docs/VERSIONING.md (3076b), hooks/hooks.json (529b), keep/__init__.py (1975b), keep/__main__.py (104b), keep/api.py (110895b), keep/backend.py (3430b), keep/cli.py (76915b), keep/config.py (23110b), keep/data/__init__.py (24b), keep/data/openclaw-plugin/index.ts (1325b), keep/data/openclaw-plugin/openclaw.plugin.json (247b), keep/data/openclaw-plugin/package.json (98b), keep/data/system/__init__.py (28b), keep/data/system/conversations.md (15732b), keep/data/system/domains.md (6095b), keep/data/system/library.md (7580b), keep/data/system/meta-album.md (175b), keep/data/system/meta-artist.md (201b), keep/data/system/meta-genre.md (195b), keep/data/system/meta-learnings.md (333b), keep/data/system/meta-todo.md (403b), keep/data/system/now.md (971b), keep/data/system/tag-act.md (2675b), keep/data/system/tag-project.md (1252b), keep/data/system/tag-status.md (2047b), keep/data/system/tag-topic.md (1431b), keep/data/system/tag-type.md (2538b), keep/document_store.py (53408b), keep/errors.py (918b), keep/integrations.py (10989b), keep/logging_config.py (2902b), keep/model_lock.py (6460b), keep/paths.py (3315b), keep/pending_summaries.py (5727b), keep/protocol.py (10681b), keep/providers/__init__.py (1094b), keep/providers/base.py (19446b), keep/providers/documents.py (22678b), keep/providers/embedding_cache.py (11243b), keep/providers/embeddings.py (14945b), keep/providers/llm.py (19039b), keep/providers/mlx.py (13853b), keep/providers/summarization.py (3610b), keep/remote.py (13549b), keep/store.py (23201b), keep/types.py (4609b), later/todo.txt (16415b), pyproject.toml (2787b), README.md (7153b), SKILL.md (10012b)\n\nArchive v0.31.0: 86 files, 343576 bytes\n\nFiles: .claude-plugin/plugin.json (186b), .claude/settings.json (529b), commands/reflect.md (4523b), CONTRIBUTING.md (2671b), docs/AGENT-GUIDE.md (5108b), docs/ARCHITECTURE.md (14639b), docs/KEEP-CONFIG.md (3510b), docs/KEEP-FIND.md (2472b), docs/KEEP-GET.md (2149b), docs/KEEP-LIST.md (2128b), docs/KEEP-NOW.md (2467b), docs/KEEP-PUT.md (3049b), docs/library/an5.57_translation-en-sujato.json (7443b), docs/library/fortytwo_chapters.txt (33053b), docs/library/han_verse.txt (3689b), docs/library/INDEX.md (7189b), docs/library/mn61.html (25229b), docs/library/mumford_sticks_and_stones.txt (264881b), docs/library/true_person_no_rank.md (7091b), docs/META-DOCS.md (4442b), docs/OPENCLAW-INTEGRATION.md (2395b), docs/OUTPUT.md (5264b), docs/PYTHON-API.md (7108b), docs/QUICKSTART.md (10949b), docs/REFERENCE.md (5591b), docs/RELEASING.md (1442b), docs/SYSTEM-TAGS.md (4942b), docs/TAGGING.md (5162b), docs/VERSIONING.md (2546b), hooks/hooks.json (529b), keep/__init__.py (1619b), keep/__main__.py (104b), keep/api.py (94466b), keep/cli.py (71311b), keep/config.py (19024b), keep/data/__init__.py (24b), keep/data/openclaw-plugin/index.ts (1325b), keep/data/openclaw-plugin/openclaw.plugin.json (247b), keep/data/openclaw-plugin/package.json (98b), keep/data/system/__init__.py (28b), keep/data/system/conversations.md (15732b), keep/data/system/domains.md (6095b), keep/data/system/library.md (7580b), keep/data/system/meta-learnings.md (333b), keep/data/system/meta-todo.md (403b), keep/data/system/now.md (971b), keep/data/system/tag-act.md (2675b), keep/data/system/tag-project.md (1252b), keep/data/system/tag-status.md (2047b), keep/data/system/tag-topic.md (1431b), keep/data/system/tag-type.md (2538b), keep/document_store.py (37113b), keep/errors.py (918b), keep/integrations.py (10977b), keep/logging_config.py (2902b), keep/model_lock.py (5607b), keep/paths.py (3315b), keep/pending_summaries.py (5727b), keep/providers/__init__.py (1094b), keep/providers/base.py (17149b), keep/providers/documents.py (12013b), keep/providers/embedding_cache.py (11243b), keep/providers/embeddings.py (14945b), keep/providers/llm.py (16981b), keep/providers/mlx.py (9047b), keep/providers/summarization.py (3610b), keep/store.py (20163b), keep/types.py (3366b), later/todo.txt (17186b), pyproject.toml (2401b), README.md (7004b), SKILL.md (9370b), tests/__init__.py (24b), tests/conftest.py (14616b), tests/test_cli.py (21993b), tests/test_config_command.py (15102b), tests/test_core.py (17767b), tests/test_document_store.py (21520b), tests/test_embedding_cache.py (10820b), tests/test_embedding_identity.py (1367b)\n\nArchive v0.30.2: 77 files, 339353 bytes\n\nFiles: .claude-plugin/plugin.json (186b), .claude/settings.json (529b), commands/reflect.md (4523b), CONTRIBUTING.md (2671b), docs/AGENT-GUIDE.md (23023b), docs/ARCHITECTURE.md (14639b), docs/library/an5.57_translation-en-sujato.json (7443b), docs/library/fortytwo_chapters.txt (33053b), docs/library/han_verse.txt (3689b), docs/library/INDEX.md (7189b), docs/library/mn61.html (25229b), docs/library/mumford_sticks_and_stones.txt (264881b), docs/library/true_person_no_rank.md (7091b), docs/META-DOCS.md (4442b), docs/OPENCLAW-INTEGRATION.md (2395b), docs/PYTHON-API.md (7112b), docs/QUICKSTART.md (10949b), docs/REFERENCE.md (14054b), docs/RELEASING.md (1442b), docs/SYSTEM-TAGS.md (4942b), hooks/hooks.json (529b), keep/__init__.py (1619b), keep/__main__.py (104b), keep/api.py (94324b), keep/cli.py (70773b), keep/config.py (19024b), keep/data/__init__.py (24b), keep/data/openclaw-plugin/index.ts (1325b), keep/data/openclaw-plugin/openclaw.plugin.json (247b), keep/data/openclaw-plugin/package.json (98b), keep/data/system/__init__.py (28b), keep/data/system/conversations.md (15732b), keep/data/system/domains.md (6095b), keep/data/system/library.md (7580b), keep/data/system/meta-learnings.md (333b), keep/data/system/meta-todo.md (403b), keep/data/system/now.md (971b), keep/data/system/tag-act.md (2675b), keep/data/system/tag-project.md (1252b), keep/data/system/tag-status.md (2047b), keep/data/system/tag-topic.md (1431b), keep/data/system/tag-type.md (2538b), keep/document_store.py (37113b), keep/errors.py (918b), keep/integrations.py (10977b), keep/logging_config.py (2902b), keep/model_lock.py (6476b), keep/paths.py (3315b), keep/pending_summaries.py (5727b),...","readmeExcerpt":"Skill: Reflective Memory Owner: hughpyle Summary: Reflective Memory Tags: latest:0.109.0, v0.8.1:0.8.1 Version history: v0.109.0 | 2026-03-24T11:19:23.501Z | auto Major update with expanded API, flow-based operations, and enhanced documentation. - Introduces new flow-based API (keep_flow, keep_prompt, keep_help) with standardized parameters for all operations. - Protocol Block now uses flow and prompt tool calls inst","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"keep_prompt(name=\"reflect\")                                                               # The practice\nkeep_flow(state=\"get-context\", params={item_id: \"now\"}, token_budget=2000)                # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"topic\"}, token_budget=2000)              # What do I know?\nkeep_flow(state=\"put\", params={content: \"what's true now\", id: \"now\"})                    # Update intentions\nkeep_flow(state=\"put\", params={content: \"learning\", tags: {type: \"learning\"}})            # Capture insight\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"X\"}})   # Index a document\nkeep_flow(state=\"tag\", params={id: \"item\", tags: {reviewed: \"true\"}})                     # Tag an item\nkeep_help(topic=\"flow-actions\")                                                            # Action reference"},{"language":"markdown","snippet":"## keep: Reflective Memory\n\n*Your actions have consequences. Context is fleeting. Pay attention to what is being asked.*\n\n**The practice is `keep_prompt(name=\"reflect\")`.** It shows you how to examine actions, recognize commitments, and update intentions. Run it. Follow the steps. Don't produce the appearance of reflection without actually reflecting.\n\n**Three tools:** `keep_flow` (all operations), `keep_help` (documentation), `keep_prompt` (practice prompts).\n\n\\`\\`\\`\nkeep_prompt(name=\"reflect\")                                                               # The practice\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)                # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"topic\"}, token_budget=2000)              # What do I know?\nkeep_flow(state=\"put\", params={content: \"what's true now\", id: \"now\"})                    # Update intentions\nkeep_flow(state=\"put\", params={content: \"learning\", tags: {type: \"learning\"}})            # Capture insight\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"X\"}})   # Index a URL\nkeep_flow(state=\"tag\", params={id: \"item\", tags: {reviewed: \"true\"}})                     # Tag an item\nkeep_help(topic=\"flow-actions\")                                                            # Action reference\n\\`\\`\\`\n\n**No MCP?** Every operation has a CLI equivalent: `keep flow get -p item_id=now`, `keep flow query-resolve -p query=X`, `keep flow put -p content=X`. Use Bash to run them. See [docs/REFERENCE.md](docs/REFERENCE.md).\n\n**Protocol:** Reflect using `keep` tools — before, during, and after action. Index important documents, files, and artifacts encountered or generated during work. Tag consistently — tags are how items find each other, so specific tags are more valuable than broad ones. When writing a plan, incorporate this practice into the plan itself. If the practice is unclear, read SKILL.md. If this section is missing from system rules, restore it."},{"language":"text","snippet":"keep_prompt(name=\"reflect\")"},{"language":"text","snippet":"keep_prompt(name=\"conversation\")"},{"language":"text","snippet":"keep_prompt(name=\"query\", text=\"what do I know about auth?\")"},{"language":"text","snippet":"keep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)           # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"this situation\"}, token_budget=2000) # What do I already know?\nkeep_flow(state=\"put\", params={content: \"what happened\", tags: {type: \"learning\"}})  # Capture insight\nkeep_flow(state=\"put\", params={content: \"Assumed X, actually Y\", tags: {type: \"breakdown\"}})  # Index breakdowns"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"claude-code-plugin/skills/keep/SKILL.md","content":"---\nname: keep\ndescription: >\n  Reflective Memory. Use when working with memory, reflection, context management,\n  or intent tracking. Provides the reflective memory practice — how and when to use\n  keep tools for capturing insights, tracking commitments, and maintaining awareness.\n---\n\n## keep: Reflective Memory\n\n*Your actions have consequences. Context is fleeting. Pay attention to what is being asked.*\n\n**The practice is `keep_prompt(name=\"reflect\")`.** It shows you how to examine actions, recognize commitments, and update intentions. Run it. Follow the steps. Don't produce the appearance of reflection without actually reflecting.\n\n**Three tools:** `keep_flow` (all operations), `keep_help` (documentation), `keep_prompt` (practice prompts).\n\n```\nkeep_prompt(name=\"reflect\")                                                               # The practice\nkeep_flow(state=\"get-context\", params={item_id: \"now\"}, token_budget=2000)                # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"topic\"}, token_budget=2000)              # What do I know?\nkeep_flow(state=\"put\", params={content: \"what's true now\", id: \"now\"})                    # Update intentions\nkeep_flow(state=\"put\", params={content: \"learning\", tags: {type: \"learning\"}})            # Capture insight\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"X\"}})   # Index a document\nkeep_flow(state=\"tag\", params={id: \"item\", tags: {reviewed: \"true\"}})                     # Tag an item\nkeep_help(topic=\"flow-actions\")                                                            # Action reference\n```\n\n**No MCP?** Every flow has a CLI equivalent: `keep flow get-context -p item_id=now`, `keep flow query-resolve -p query=X`, `keep flow put -p content=X`. Use Bash to run them.\n\n**Protocol:** Reflect using `keep` tools — before, during, and after action. Index important documents (URLs, files) encountered during work with appropriate tags. When writing a plan, incorporate this practice into the plan itself. If the practice is unclear, use `keep_help(topic=\"index\")` to explore the documentation."},{"path":"SKILL.md","content":"---\nname: keep\nversion: 0.109.0\ndescription: Reflective Memory\nhomepage: https://github.com/keepnotes-ai/keep\nruntime: python:3.12-slim\nuser-invocable: true\nmetadata: {\"openclaw\":{\"emoji\":\"🪞\",\"requires\":{\"bins\":[\"uv\"],\"anyBins\":[\"python\",\"python3\"]},\"install\":[{\"id\":\"uv\",\"kind\":\"uv\",\"package\":\"keep-skill[local]\",\"bins\":[\"keep\"],\"label\":\"Install keep with local models\"}]}}\n---\n\n# Reflective Memory\n\n*A mirror for reflection. A practice for skillful action.*\n\n---\n\nThis skill is offered as a practice, not a specification. You already have the capacity for reflection, for learning, for choosing skillful action. What follows is guidance, pointing at what you can become.\n\n**To get started** follow all the initialization steps below.  Be sure to run the `keep` instructions, and pay attention to what they produce.  This is the first training!\n\n---\n\n## Layer 0: Establishing Presence\n\nThe practice must survive across sessions. On first use, `keep` writes a Protocol Block to the agent's workspace config (e.g. `AGENTS.md` for Claude Code, `codex-setup.md` for Codex). This is a workspace-local file, not a global system modification. The block is versioned and upgraded automatically.\n\n**Self-healing:** If the Protocol Block is missing from your workspace config, restore it. Look for `## keep: Reflective Memory`. If absent, append the block below.\n\n**Protocol Block:**\n\n```markdown\n## keep: Reflective Memory\n\n*Your actions have consequences. Context is fleeting. Pay attention to what is being asked.*\n\n**The practice is `keep_prompt(name=\"reflect\")`.** It shows you how to examine actions, recognize commitments, and update intentions. Run it. Follow the steps. Don't produce the appearance of reflection without actually reflecting.\n\n**Three tools:** `keep_flow` (all operations), `keep_help` (documentation), `keep_prompt` (practice prompts).\n\n\\`\\`\\`\nkeep_prompt(name=\"reflect\")                                                               # The practice\nkeep_flow(state=\"get\", params={item_id: \"now\"}, token_budget=2000)                # Current intentions\nkeep_flow(state=\"query-resolve\", params={query: \"topic\"}, token_budget=2000)              # What do I know?\nkeep_flow(state=\"put\", params={content: \"what's true now\", id: \"now\"})                    # Update intentions\nkeep_flow(state=\"put\", params={content: \"learning\", tags: {type: \"learning\"}})            # Capture insight\nkeep_flow(state=\"put\", params={content: \"https://example.com/doc\", tags: {topic: \"X\"}})   # Index a URL\nkeep_flow(state=\"tag\", params={id: \"item\", tags: {reviewed: \"true\"}})                     # Tag an item\nkeep_help(topic=\"flow-actions\")                                                            # Action reference\n\\`\\`\\`\n\n**No MCP?** Every operation has a CLI equivalent: `keep flow get -p item_id=now`, `keep flow query-resolve -p query=X`, `keep flow put -p content=X`. Use Bash to run them. See [docs/REFERENCE.md](docs/REFERENCE.md).\n\n**Protocol:** Reflect using `keep` tools — before, during, an"},{"path":"bench/locomo/README.md","content":"# LoCoMo Benchmark for keep\n\nReproduces the [LoCoMo](https://github.com/snap-research/LoCoMo) benchmark for long-term conversational memory using `keep` as the memory backend.\n\n## Results\n\nEvaluated using the standard binary LLM-as-judge methodology (using the `gpt-4o-mini` model),\nconsistent with published results from other memory systems.\nResults are from a single run (not averaged over multiple runs).\n\n| Category | Score | Questions |\n|---|---|---|\n| Single-hop | 86.2% | 841 |\n| Temporal | 68.5% | 321 |\n| Multi-hop | 64.2% | 282 |\n| Open-domain | 50.0% | 96 |\n| **Overall** | **76.2%** | **1540** |\n\n\n### Stack\n\n| Component | Model | Location |\n|---|---|---|\n| Embeddings | nomic-embed-text | Local (Ollama) |\n| Analysis/summarization | llama3.2:3b | Local (Ollama) |\n| Query answering | gpt-4o-mini | OpenAI API |\n| Judge | gpt-4o-mini | OpenAI API |\n\nkeep's embedding and summarization providers (and their prompts) are user-configurable.\nThis benchmark used local Ollama models, but keep also supports OpenAI, Anthropic,\nand other API providers, as well as the [keepnotes.ai](https://keepnotes.ai)\nhosted service.\n\n### Comparison with published results\n\nFor context, here are publicly reported LoCoMo scores from other memory systems,\nsourced from [Memobase](https://github.com/memodb-io/memobase/tree/main/docs/experiments/locomo-benchmark)\nand [MemMachine](https://memmachine.ai/blog/2025/09/memmachine-reaches-new-heights-on-locomo/).\nMethodologies vary across systems (different models, retrieval strategies,\njudge configurations), so these are reference points rather than\nstrict apples-to-apples comparisons.\n\n| System | Single-hop | Temporal | Multi-hop | Open-domain | Overall |\n|---|---|---|---|---|---|\n| MemMachine | 93.3 | 72.6 | 80.5 | 64.6 | 84.9 |\n| **keep** | **86.2** | **68.5** | **64.2** | **50.0** | **76.2** |\n| Memobase v0.0.37 | 70.9 | 85.1 | 46.9 | 77.2 | 75.8 |\n| Zep | 74.1 | 79.8 | 66.0 | 67.7 | 75.1 |\n| Mem0 | 67.1 | 55.5 | 51.2 | 72.9 | 66.9 |\n| LangMem | 62.2 | 23.4 | 47.9 | 71.1 | 58.1 |\n| OpenAI | 63.8 | 21.7 | 42.9 | 62.3 | 52.9 |\n\n## Dataset\n\nDownload `locomo10.json` from [snap-research/LoCoMo](https://github.com/snap-research/LoCoMo/tree/main/data)\nand place it in `dataset/`.\n\nThe dataset contains 10 multi-session conversations between character pairs,\nwith 1,986 QA items across 5 categories:\n\n| Category | Questions | Description |\n|---|---|---|\n| Single-hop | 841 | Factual recall from a single session |\n| Temporal | 321 | Time/date reasoning across sessions |\n| Multi-hop | 282 | Synthesizing facts from multiple sessions |\n| Open-domain | 96 | Integrating conversation context with world knowledge |\n| Adversarial | 446 | Questions about things never discussed (expect refusal) |\n\n**Note on category numbering:** The paper's numbered list (1-5) does not match\nthe category IDs in the dataset JSON. See [MemMachine's Appendix A](https://memmachine.ai/blog/2025/09/memmachine-reaches-new-heights-on-locomo/#appendix-a)\nfor the correct mappin"},{"path":"langchain-keep/README.md","content":"# langchain-keep\n\nLangChain integration for [keep](https://github.com/keepnotes-ai/keep) — reflective memory for AI agents.\n\nThis is a convenience package that installs `keep-skill[langchain]` and re-exports the integration components.\n\n## Installation\n\n```bash\npip install langchain-keep\n```\n\n## Usage\n\n```python\nfrom langchain_keep import KeepStore, KeepNotesToolkit, KeepNotesRetriever\n\n# LangGraph BaseStore\nstore = KeepStore()\n\n# LangChain tools\nfrom keep import Keeper\ntoolkit = KeepNotesToolkit(keeper=Keeper())\ntools = toolkit.get_tools()\n\n# RAG retriever\nretriever = KeepNotesRetriever(keeper=Keeper(), k=5)\n```\n\n## What's included\n\n| Component | Description |\n|-----------|-------------|\n| `KeepStore` | LangGraph `BaseStore` backed by Keep |\n| `KeepNotesToolkit` | 4 LangChain tools (remember, recall, get/set context) |\n| `KeepNotesRetriever` | `BaseRetriever` with optional now-context |\n| `KeepNotesMiddleware` | LCEL runnable for auto-injecting memory context |\n\n## Configuration\n\nYou need an embedding provider configured. Simplest:\n\n```bash\nexport OPENAI_API_KEY=...    # or GEMINI_API_KEY\n```\n\nOr use the hosted service:\n\n```bash\nexport KEEPNOTES_API_KEY=... # Sign up at https://keepnotes.ai\n```\n\nSee the [full documentation](https://docs.keepnotes.ai) for all provider options.\n\n## Links\n\n- [Documentation](https://docs.keepnotes.ai)\n- [GitHub](https://github.com/keepnotes-ai/keep)\n- [keep on PyPI](https://pypi.org/project/keep-skill/)"},{"path":"README.md","content":"# keep\n\nAn agent-skill: memory that pays attention.\n\nIt includes [skill instructions](SKILL.md) for reflective practice, and a powerful semantic memory system with [command-line](docs/QUICKSTART.md) and [MCP](docs/KEEP-MCP.md) interfaces. Fully local, or use API keys for model providers, or [cloud-hosted](https://keepnotes.ai) for multi-agent use.\n\n```bash\nuv tool install keep-skill       # or: pip install keep-skill\nexport OPENAI_API_KEY=...        # Or GEMINI_API_KEY (both do embeddings + summarization)\n\n# Index content (store auto-initializes on first use)\nkeep put https://inguz.substack.com/p/keep -t topic=practice\nkeep put \"Rate limit is 100 req/min\" -t topic=api\n\n# Index a codebase — recursive, with daemon-driven watch for changes\nkeep put ./my-project/ -r --watch\n\n# Search by meaning\nkeep find \"what's the rate limit?\"\n\n# Track what you're working on\nkeep now \"Debugging auth flow\"\n\n# Instructions for reflection\nkeep prompt reflect\n```\n\n---\n\n## What It Does\n\nStore anything — notes, files, URLs — and `keep` summarizes, embeds, and tags each item. You search by meaning, not keywords. Content goes in as text, PDF, HTML, Office documents, audio, or images; what comes back is a summary with tags and semantic neighbors. Audio and image files auto-extract metadata tags (artist, album, camera, date, etc.).\n\nWhat makes this more than a vector store: tags become edges. Define a tag like `author` or `git_commit` and keep creates bidirectional links — a user-defined graph model where every tag can be a navigable relationship. When you retrieve any item, keep follows these edges and fires standing queries — surfacing open commitments, past learnings, referenced files, commit history. The right things appear at the right time, without manual graph construction.\n\n- **Summarize, embed, tag** — URLs, files, and text are summarized and indexed on ingest\n- **Contextual feedback** — Open commitments and past learnings surface automatically\n- **Semantic search** — Find by meaning, not keywords; scope to a folder or project\n- **Tag organization** — Speech acts, status, project, topic, type — structured and queryable\n- **Deep search** — Follow edges and tags from results to discover related items across the graph\n- **Edge tags** — Turn tags into navigable relationships with automatic inverse links\n- **Git changelog** — Commits indexed as searchable items with edges to touched files\n- **Parts** — `analyze` decomposes documents into searchable sections, each with its own embedding and tags\n- **Strings** — Every note is a string of versions; reorganize history by meaning with `keep move`\n- **Watches** — Daemon-driven directory and file monitoring; re-indexes on change\n- **Works offline** — Local models (MLX, Ollama), or API providers (Voyage, OpenAI, Gemini, Anthropic, Mistral)\n\nBacked by ChromaDB for vectors, SQLite for metadata and versions.\n\n> **[keepnotes.ai](https://keepnotes.ai)** — Hosted service. No local setup, no API keys to manage. Same SDK, managed infras"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Reflective Memory Skill: Reflective Memory Owner: hughpyle Summary: Reflective Memory Tags: latest:0.109.0, v0.8.1:0.8.1 Version history: v0.109.0 | 2026-03-24T11:19:23.501Z | auto Major update with expanded API, flow-based operations, and enhanced documentation. - Introduces new flow-based API (keep_flow, keep_prompt, keep_help) with standardized parameters for all operations. - Protocol Block now uses flow and prompt tool calls inst","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1873,"uniquenessScore":46,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-09T08:19:07.107Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-09T08:19:07.107Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-09T13:29:59.264Z","emptyReason":null},"items":[{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-10T18:48:31.762Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}