Status: Final Author: Dennis Kittrell Date: 2026-03-14 Repo: Percona-Lab/NAPSAC
NAPSAC is a Claude plugin that provides persistent AI memory using Notion as the only storage backend. It is a lightweight alternative to PACK — the knapsack you grab when you don't need the full pack.
NAPSAC exposes five tools (memory_init, memory_list, memory_get, memory_update, memory_search) that match PACK's signatures so system prompts work interchangeably between the two products. Unlike PACK, NAPSAC requires zero infrastructure: no GitHub repo, no MCP server, no API tokens, no config files, no local install.
The plugin is the authoritative implementation, providing validated naming, enforced page structure, and guaranteed index regeneration. A system prompt fallback serves tools where the plugin isn't available (Claude mobile, ChatGPT, Cursor, VS Code).
PACK is powerful but has a setup cost: GitHub repo, personal access token, local MCP server, env file. For users who primarily use Claude, ChatGPT, or other tools with native Notion access, this infrastructure is unnecessary friction.
Notion solves this because:
- Universal access. Notion works on every device — desktop, mobile, tablet, web. Memory is always reachable.
- Zero infrastructure. No server to run, no repo to maintain, no tokens to rotate. OAuth handles auth.
- Native connectors exist. Claude has a built-in Notion connector. ChatGPT, Cursor, and VS Code support Notion MCP. The plumbing already exists.
- Version history built in. Notion tracks page edit history natively. No git needed for audit trails.
- Sharing is native. Want to share specific memory with a teammate? Share the Notion page. Permissions are granular.
- Human-editable. Users can read and edit their memory directly in Notion. No terminal required.
| Dimension | NAPSAC (Notion) | PACK (GitHub) |
|---|---|---|
| Setup | Zero config | GitHub token + MCP server |
| Version history | Notion page history (limited) | Full git log with commits, diffs, SHAs |
| CLI access | None | Full CLI (pack list, pack get, etc.) |
| Offline access | No (requires Notion API) | Yes (with local git connector) |
| Token efficiency | Notion API overhead per request | Direct file reads, minimal overhead |
| Concurrency | Last-write-wins | SHA-based optimistic concurrency |
| Webhook/sync | None | Webhook + built-in Notion/Google Docs sync |
| Backup/export | Notion export only | Git clone, standard backup tools |
| Encryption | Notion's encryption at rest | User controls repo encryption |
| Multi-client | Any tool with Notion access | Any MCP client |
NAPSAC and PACK serve different user profiles:
- NAPSAC user: Non-developers who use Cowork as their primary AI environment. PMs, marketers, founders, ops people. Wants memory to "just work" across devices. Values simplicity over control.
- PACK user: Developers who use Claude Code, Cursor, Windsurf, Open WebUI. Needs git history and CLI. Wants complete control over storage. Values auditability over convenience.
- Both: Power user who wants PACK's git history and CLI for serious work, but also wants mobile access. Runs PACK with Notion sync, uses NAPSAC's system prompt as a fallback.
Neither product replaces the other. They share conventions so migration between them is seamless.
- Zero infrastructure. No local server, no install, no config files. If Notion is connected, it works.
- Portable. Same file path conventions as PACK. Content migrates freely between the two.
- Plugin-first. NAPSAC is a Claude plugin for Cowork and Claude Code. The plugin is the product. The system prompt is the fallback.
- Prompt-compatible. System prompts work interchangeably with PACK. Swap one for the other without rewriting prompts.
- Notion-native. Content is stored as proper Notion blocks, not raw markdown dumps. Pages look good in Notion.
NAPSAC's entire value proposition is zero config. An MCP server requires local install, config files, and running a process. That's PACK.
A Claude plugin runs inside the session. It uses Claude's native Notion connector for auth. No tokens, no env files, nothing to install.
| Consideration | Plugin | MCP Server |
|---|---|---|
| Installation | Claude installs from GitHub URL | npm install, local config |
| Auth | Notion OAuth via Claude's connector | API tokens in env file |
| Port conflicts | None (runs in-session) | Needs available port |
| Mobile | Works in Cowork | Requires desktop running |
| Cross-tool | Plugin = Cowork/Claude Code only | Works in any MCP client |
| Validation | Behavior spec in SKILL.md | Code-level validation |
The tradeoff: the plugin only works in Cowork and Claude Code. For other tools, the system prompt fallback provides the same memory access without the plugin's validation guardrails.
┌─────────────────────────────────────────┐
│ Claude Session │
│ │
│ ┌───────────────┐ ┌───────────────┐ │
│ │ NAPSAC Plugin │ │ Notion MCP │ │
│ │ (SKILL.md) │──│ (native) │ │
│ │ │ │ │ │
│ │ memory_init │ │ notion-search │ │
│ │ memory_list │ │ notion-fetch │ │
│ │ memory_get │ │ notion-create │ │
│ │ memory_update │ │ notion-update │ │
│ │ memory_search │ │ │ │
│ └───────────────┘ └───────┬───────┘ │
│ │ │
└──────────────────────────────┼──────────┘
│
┌──────────▼──────────┐
│ Notion API │
│ (OAuth, no tokens) │
└──────────┬──────────┘
│
┌──────────▼──────────┐
│ User's Notion │
│ Workspace │
│ │
│ [Memory Root] │
│ ├── _index │
│ ├── _conventions │
│ ├── context/ │
│ ├── projects/ │
│ ├── profiles/ │
│ └── contacts/ │
└─────────────────────┘
NAPSAC is a skill definition (SKILL.md) that instructs Claude how to use Notion MCP tools to implement memory operations. There is no server process, no compiled code, no runtime. The "plugin" is a behavior specification that Claude follows — but it provides real validation, naming enforcement, and guaranteed index regeneration that the system prompt alone cannot.
┌─────────────────────────────────────────────────┐
│ Plugin (Cowork / Claude Code) │
│ Validated naming, enforced structure, │
│ guaranteed index regen, error handling │
├─────────────────────────────────────────────────┤
│ System Prompt (Claude mobile/web, │
│ ChatGPT, Cursor, VS Code) │
│ Best-effort compliance with _conventions, │
│ depends on AI reading and following rules │
├─────────────────────────────────────────────────┤
│ Native Memory (last resort) │
│ No persistence. Context may be incomplete. │
└─────────────────────────────────────────────────┘
The plugin is the reliable, validated tier. The system prompt is the cross-tool compatibility tier. Native memory is the last resort.
| NAPSAC Tool | Notion Operations Used |
|---|---|
memory_init |
Create pages (index + conventions + starter content) |
memory_list |
Fetch index page content |
memory_get |
Search by title → fetch page content |
memory_update |
Search by title → update or create page → regenerate index |
memory_search |
Notion search API across all child pages |
Notion databases were considered but rejected:
- Page hierarchy is more natural. Directories map to parent pages. Files map to child pages. This mirrors PACK's filesystem structure.
- No schema to maintain. Databases require property definitions. Pages are freeform.
- Better for rich content. Database entries are optimized for structured data. Memory files contain freeform text with headings, bullets, and code blocks.
- Simpler API operations. Creating a child page is one API call. Creating a database entry with properties is more complex.
Each leaf page's title is its full path (e.g., context/preferences, not just preferences). This ensures:
- Unique identification. No ambiguity between files in different directories.
- Search-friendly. Searching for
context/preferencesin Notion returns exactly one result. - PACK compatibility. Paths match PACK's file paths (minus the
.mdextension).
The _conventions page is the bridge between the plugin and the system prompt fallback.
In plugin mode: The plugin validates naming and structure directly. _conventions exists as human-readable documentation.
In system prompt mode: The system prompt instructs the AI to read _conventions before writing. This is the only mechanism that ensures naming consistency, directory structure, and content format across tools like ChatGPT and Cursor.
_conventions is created once during memory_init and never modified during normal operations. It is a system page.
The _index page is auto-regenerated on every memory_update. It serves the same purpose as PACK's index.md:
- Session start discovery. Agents read this first (~700 tokens) to decide what to load.
- Human overview. Users browsing Notion see a summary of everything in memory.
- Cross-tool compatibility. Any AI tool that can read a Notion page can use the index.
The underscore prefix (_index) keeps it sorted before alphabetical content in Notion's sidebar.
PACK uses SHA-based optimistic concurrency to prevent race conditions. NAPSAC uses Notion's native last-write-wins model.
Why no optimistic concurrency:
- Single-user product. NAPSAC is personal memory. Concurrent writes from multiple agents are rare.
- Notion doesn't expose ETags. There's no lightweight way to detect version conflicts via the Notion API.
- Page history is the safety net. If a write overwrites something important, Notion's page history allows recovery.
- Simplicity. Removing concurrency control eliminates an entire class of error handling.
Risk: If two AI sessions write to the same file simultaneously, the last write wins. This is acceptable because:
- Memory files are personal, not shared
- Simultaneous sessions writing the same file is extremely rare
- Notion page history allows recovery of overwritten content
NAPSAC converts markdown input to proper Notion blocks:
- Native rendering. Pages look correct in Notion's UI. Raw markdown in a page looks broken.
- Editability. Users can edit memory in Notion's editor naturally.
- Consistency with BINER. BINER formats pages using Notion blocks. Memory pages should follow the same standard.
## Heading → heading_2 block
### Heading → heading_3 block
- item → bulleted_list_item block
1. item → numbered_list_item block
`code block` → code block
> quote → quote block
**bold** → bold rich text
*italic* → italic rich text
plain text → paragraph block
memory_get returns content in clean readable format — not raw Notion block JSON. The plugin converts Notion blocks back to clean text that Claude can consume efficiently.
Notion API failures use exponential backoff: 1s, 2s, 4s. Three attempts maximum.
Why 3 attempts: Notion's API is generally reliable. Transient failures (rate limits, network blips) typically resolve within seconds. More than 3 retries risks masking a real problem.
Never lose a write silently. If all retries fail, the error message explicitly states that the content was not saved and suggests retrying.
The three-tier fallback (plugin → system prompt/Notion → native memory) ensures some level of context is always available. The system prompt enforces trying each level in order.
| # | Question | Decision | Rationale |
|---|---|---|---|
| 1 | Storage model | Notion sub-pages, not database | Freeform content, simpler API, mirrors filesystem |
| 2 | Concurrency | Last-write-wins | Single-user product, Notion has no ETags, page history provides safety |
| 3 | Content format | Notion blocks, not raw markdown | Native rendering, user-editable, BINER consistency |
| 4 | Page naming | Full file paths as titles | Unique identification, search-friendly, PACK-compatible |
| 5 | Index naming | _index with underscore prefix |
Sorts first in sidebar, avoids conflict with user content |
| 6 | Plugin vs MCP server | Plugin (SKILL.md) | Zero infrastructure, mobile-native, reuses existing Notion connector |
| 7 | Tool signatures | Match PACK exactly | System prompt portability, same mental model |
| 8 | File extensions | Omitted (no .md) |
Notion pages don't have extensions; stripped on migration from PACK |
| 9 | Directory representation | Parent pages with / suffix |
Natural Notion hierarchy, browseable in sidebar |
| 10 | Version tracking | Notion page history | No infrastructure, built-in, good enough for personal memory |
| 11 | Plugin vs system prompt | Both — plugin is authoritative, prompt is fallback | Plugin provides validation; prompt provides cross-tool reach |
| 12 | _conventions page | Created once, never auto-modified | Human-readable docs for non-plugin environments; plugin validates directly |
| Feature | Why Not |
|---|---|
| GitHub integration | That's PACK's domain. NAPSAC is Notion-only by design. |
| CLI | No local infrastructure. Memory is accessed through AI tools or Notion directly. |
| Sync to external targets | No infrastructure to run sync jobs. Use PACK if you need sync. |
| Webhook support | No server to receive or send webhooks. |
| MCP server | NAPSAC is a plugin, not a server. The distinction is intentional. |
| API tokens | OAuth only. No tokens for users to manage. |
| Local storage | Everything lives in Notion. No local state, no config files. |
| Encryption | Relies on Notion's encryption at rest. For encrypted memory, use PACK with an encrypted git repo. |