notnessie

NotNessie — Claude Code-Native Project Memory Layer

Project Summary

NotNessie is a local-first project memory layer built specifically for Claude Code.

The product helps Claude Code remember important project context across sessions, tasks, and repositories. Instead of starting every coding task from zero, Claude Code can query NotNessie for previous decisions, constraints, verified commands, bug notes, architecture rules, and task summaries.

The name NotNessie is intentionally playful. The project is not a clone of Nessie’s production product. It is a focused demo that explores the same broad problem space: AI context infrastructure, memory, retrieval, provenance, and agent-facing workflows.

The core idea is:

Claude Code should become more useful over time inside a repository.

NotNessie turns previous Claude Code work into reusable, structured project memory.


Product Goal

Claude Code is powerful, but every new task often requires the same context to be explained again:

Use Fastify, not Express.
Use PostgreSQL.
Do not edit generated files.
Run tests with pnpm test.
The project uses pnpm, not npm.
Do not change the public API response format.
Do not introduce microservices for the MVP.
Use service classes instead of putting business logic inside route handlers.

NotNessie stores this kind of information and exposes it back to Claude Code at the right moment.

The goal is not to build a generic notes app, chatbot, or ChatGPT importer.

The goal is to build:

A Claude Code-native memory system for software projects.

One-Sentence Pitch

NotNessie is a Claude Code-native memory layer that captures project decisions, constraints, verified commands, bug notes, and task summaries, then exposes them back to Claude Code through MCP, hooks, skills, and a local CLI.


Target User

The target user is a developer who uses Claude Code repeatedly inside the same repositories.

This user wants Claude Code to remember:

The product is especially useful for developers who use AI heavily and want the AI to improve through accumulated project context.


Main Workflow

A developer initializes NotNessie inside a repository:

npx notnessie init

This creates project-level Claude Code integration files:

.mcp.json
CLAUDE.md
.claude/skills/notnessie/SKILL.md
.claude/settings.json
.notnessie/config.json

Then the developer opens Claude Code.

Claude Code connects to the local NotNessie MCP server.

Before starting a non-trivial task, Claude Code asks NotNessie for relevant project context.

Example user task:

Add refresh token rotation to the auth module.

Claude Code calls NotNessie:

notnessie_get_project_context

NotNessie returns a compact context pack:

Relevant project context:

Decisions:
- PostgreSQL is the main database.
- Redis stores refresh token metadata.
- Fastify plugins are preferred for request-level auth behavior.

Constraints:
- Do not change the public API response format.
- Do not manually edit generated Prisma files.

Verified commands:
- pnpm test auth
- pnpm lint

Open questions:
- Should refresh tokens be tracked per device?

Claude Code uses this context while editing the codebase.

After the task, Claude Code saves useful memory back into NotNessie:

notnessie_save_task_summary
notnessie_save_decision
notnessie_save_constraint
notnessie_save_verified_command

Over time, the repository gains a structured memory layer that Claude Code can reuse.


Core Features

1. Claude Code MCP Server

The MCP server is the main integration point.

NotNessie should expose MCP tools that Claude Code can call during coding sessions.

Example .mcp.json:

{
  "mcpServers": {
    "notnessie": {
      "type": "stdio",
      "command": "notnessie",
      "args": ["mcp"],
      "env": {
        "NOTNESSIE_PROJECT_ID": "current"
      }
    }
  }
}

Claude Code should be able to use NotNessie without needing a browser, account, or cloud service.

The MCP server should be local-first.


2. Claude Code Skill

NotNessie should include a Claude Code skill that teaches Claude when and how to use the system.

Generated skill path:

.claude/skills/notnessie/SKILL.md

The skill should instruct Claude Code to:

Query NotNessie before non-trivial work.
Search memory when the task mentions architecture, database, APIs, tests, deployment, bugs, or existing project rules.
Save useful task summaries after work.
Save decisions when architectural or implementation choices are made.
Save constraints when the user gives rules.
Save verified commands after successful command execution.
Avoid saving secrets, tokens, credentials, and huge raw logs.
Prefer current code over old memory when they conflict.

Example skill file:

---
name: notnessie
description: Use NotNessie to retrieve and save project memory during Claude Code sessions.
---

# NotNessie Skill

Use NotNessie whenever the task may depend on project history, previous decisions, coding preferences, setup commands, constraints, or unresolved TODOs.

## Before starting work

Call:

- `notnessie_get_project_context`
- `notnessie_search_memory` when the task mentions a specific feature, module, file, bug, database, API, or architecture topic.

Use returned memories as background context.

Current code is more authoritative than old memory. If memory conflicts with the current codebase, mention the conflict instead of blindly following memory.

## During work

If the user gives a correction, rule, or preference, save it.

Examples:

- “Don’t use Express here” → save as preference or constraint.
- “We already decided to use PostgreSQL” → save as decision.
- “Never edit generated files” → save as constraint.
- “Run tests with pnpm test” → save as verified command.

## After work

Before the final response, save a short task summary if the task produced useful future context.

Save:

- decisions made
- files changed
- commands verified
- failed approaches
- new TODOs
- important constraints discovered

Do not save secrets, API keys, tokens, credentials, private keys, or unnecessary raw logs.

3. Claude Code Hooks

Hooks make NotNessie feel automatic.

The MVP should use Claude Code hooks to capture useful lifecycle events.

Recommended hook events:

SessionStart
UserPromptSubmit
PostToolUse
Stop
PreCompact

Hook behavior:

SessionStart:
- Check whether NotNessie is available.
- Load compact project context.
- Warn if the MCP server is unavailable.

UserPromptSubmit:
- Use the user’s task prompt to retrieve relevant project memories.
- Prepare a compact context pack for Claude Code.

PostToolUse:
- Track useful command results.
- Detect verified commands.
- Optionally capture changed file paths.

Stop:
- Save a task summary if the session produced useful project knowledge.
- Save new decisions, constraints, TODOs, and bug notes when detected.

PreCompact:
- Save a summary before Claude Code compacts its context.

Example hook config:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notnessie hook session-start"
          }
        ]
      }
    ],
    "Stop": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notnessie hook stop"
          }
        ]
      }
    ],
    "PreCompact": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "notnessie hook pre-compact"
          }
        ]
      }
    ]
  }
}

Hooks should be conservative.

They should not save huge transcripts or raw terminal dumps by default.


4. Project Memory Database

NotNessie should store structured memory per repository.

Memory should be tied to a project, not just a global user profile.

Each repository gets its own memory space.

Example memory types:

type MemoryType =
  | "project_fact"
  | "decision"
  | "preference"
  | "constraint"
  | "verified_command"
  | "task_summary"
  | "bug_note"
  | "failed_attempt"
  | "todo"
  | "open_question";

Memory model:

type Memory = {
  id: string;
  projectId: string;
  type: MemoryType;
  title: string;
  summary: string;
  reasoning?: string;
  topic?: string;
  confidence: number;
  source: MemorySource;
  tags: string[];
  appliesToFiles?: string[];
  isPinned: boolean;
  isDeleted: boolean;
  createdAt: Date;
  updatedAt: Date;
};

Source model:

type MemorySource = {
  kind: "claude_code_session" | "hook" | "manual" | "mcp_tool";
  sessionId?: string;
  task?: string;
  filePaths?: string[];
  command?: string;
  createdAt: Date;
};

5. Context Pack Generation

The most important output of NotNessie is a compact context pack.

Claude Code should not receive a giant memory dump.

It should receive only the most relevant information for the current task.

Example context pack:

# NotNessie Context Pack

Task: Implement auth middleware

Relevant decisions:
- Use Fastify plugins for middleware-style behavior.
- JWT validation belongs in the auth plugin, not inside every route.
- PostgreSQL is the main database.

Constraints:
- Do not change public API response format.
- Do not edit generated Prisma files.
- Keep auth errors consistent with existing error format.

Verified commands:
- pnpm test auth
- pnpm lint

Open questions:
- Should refresh tokens be stored per-device?

Relevant files:
- src/auth/auth.service.ts
- src/plugins/auth.plugin.ts
- src/auth/auth.test.ts

Retrieval should rank memory by:

Current repository
Current task text
Mentioned files
Mentioned technologies
Memory type
Recency
Confidence
Pinned status

6. Memory Capture

NotNessie should save only useful future context.

It should save:

Architectural decisions
Implementation decisions
Project constraints
User corrections
Coding preferences
Verified commands
Failed approaches
Bug root causes
Important TODOs
Unresolved questions
Repository setup knowledge

It should not save:

Small talk
Temporary thoughts
Secrets
API keys
Tokens
Credentials
Huge raw transcripts
Full terminal output
Large generated code blocks
Private keys
.env contents

Memory capture should be conservative.

Bad memory:

The user said okay.

Good memory:

Decision: Use BullMQ for background jobs because the project already depends on Redis and needs retry support.

MCP Tools

The MCP server should expose a small set of practical tools.

notnessie_get_project_context

Purpose:

Return the most relevant context for the current repository and task.

Input:

{
  "projectPath": "/path/to/repo",
  "task": "Implement refresh token rotation",
  "limit": 10
}

Output:

{
  "project": "backend-api",
  "context": [
    {
      "id": "mem_123",
      "type": "decision",
      "title": "Use Redis for refresh token metadata",
      "summary": "Refresh token metadata is stored in Redis so token rotation can invalidate old tokens quickly.",
      "confidence": 0.91,
      "source": {
        "kind": "claude_code_session",
        "sessionId": "session_456",
        "createdAt": "2026-06-26T12:30:00Z"
      }
    }
  ]
}

notnessie_search_memory

Purpose:

Search project memory for a specific topic.

Input:

{
  "query": "database migration rules",
  "types": ["decision", "constraint", "verified_command"],
  "limit": 8
}

Output:

{
  "results": [
    {
      "id": "mem_001",
      "type": "constraint",
      "title": "Do not manually edit generated Prisma migrations",
      "summary": "Migration files should be generated through the Prisma workflow instead of edited manually.",
      "confidence": 0.86
    }
  ]
}

notnessie_save_decision

Purpose:

Save an architectural or implementation decision made during a Claude Code session.

Input:

{
  "title": "Use BullMQ for background jobs",
  "summary": "The project will use BullMQ because the app already depends on Redis and needs reliable job retries.",
  "reasoning": "BullMQ is simple, Node-native, and avoids introducing a heavier external queue system.",
  "topic": "Background Jobs",
  "source": {
    "sessionId": "current",
    "task": "Add email queue"
  }
}

Output:

{
  "saved": true,
  "memoryId": "mem_789"
}

notnessie_save_preference

Purpose:

Save a user or project coding preference.

Input:

{
  "title": "Prefer explicit service classes",
  "summary": "Business logic should live in explicit service classes instead of route handlers.",
  "topic": "Backend Style"
}

notnessie_save_constraint

Purpose:

Save a hard project rule that Claude Code should follow later.

Input:

{
  "title": "Do not edit generated files",
  "summary": "Generated files should not be manually edited. Update the source schema or generator instead.",
  "severity": "high",
  "appliesTo": ["generated", "prisma", "openapi"]
}

notnessie_save_verified_command

Purpose:

Save a command that successfully worked in this repository.

Input:

{
  "command": "pnpm test auth",
  "purpose": "Run authentication test suite",
  "exitCode": 0
}

notnessie_save_task_summary

Purpose:

Save a useful summary after a coding task.

Input:

{
  "task": "Fix login refresh token bug",
  "summary": "The bug was caused by refresh token rotation not updating the Redis key expiry.",
  "filesChanged": [
    "src/auth/auth.service.ts",
    "src/auth/auth.test.ts"
  ],
  "commandsRun": [
    "pnpm test auth"
  ],
  "outcome": "completed",
  "newTodos": [
    "Add integration test for expired refresh tokens"
  ]
}

notnessie_get_open_questions

Purpose:

Return unresolved project questions Claude Code should be aware of.

Output:

{
  "openQuestions": [
    {
      "id": "mem_222",
      "title": "Should refresh tokens be stored per-device?",
      "summary": "Previous auth work raised this question, but no final decision was made.",
      "topic": "Authentication"
    }
  ]
}

notnessie_get_verified_commands

Purpose:

Return commands that were previously verified for this repository.

Output:

{
  "commands": [
    {
      "command": "pnpm test",
      "purpose": "Run all tests",
      "lastVerifiedAt": "2026-06-26T11:00:00Z"
    },
    {
      "command": "pnpm test auth",
      "purpose": "Run auth-specific tests",
      "lastVerifiedAt": "2026-06-26T11:30:00Z"
    }
  ]
}

CLI Commands

The CLI should support developer usage and Claude Code automation.

Suggested commands:

notnessie init
notnessie dev
notnessie status
notnessie mcp
notnessie search "database rules"
notnessie context "implement auth middleware"
notnessie memory list
notnessie memory delete <id>
notnessie hook session-start
notnessie hook stop
notnessie hook pre-compact

Command purposes:

notnessie init
Creates .mcp.json, CLAUDE.md snippet, .claude skill file, hook config, and project config.

notnessie dev
Runs the local daemon and optional dashboard.

notnessie status
Checks whether the database, MCP server, hooks, and project config are working.

notnessie mcp
Starts the stdio MCP server.

notnessie search
Searches project memory manually.

notnessie context
Generates a context pack manually.

notnessie hook session-start
Runs the SessionStart hook behavior.

notnessie hook stop
Runs the Stop hook behavior.

notnessie hook pre-compact
Saves compact session memory before Claude Code context compaction.

Setup Flow

Developer runs:

npx notnessie init

Generated project files:

.mcp.json
CLAUDE.md
.claude/skills/notnessie/SKILL.md
.claude/settings.json
.notnessie/config.json

Example .notnessie/config.json:

{
  "projectName": "my-project",
  "memoryMode": "conservative",
  "autoSaveTaskSummaries": true,
  "autoSaveCommands": true,
  "autoSaveFileChanges": false,
  "redactSecrets": true
}

Claude Code starts with:

claude --mcp-config ./.mcp.json

Or normally, if Claude Code detects the project configuration:

claude

Optional Local Dashboard

The dashboard is useful for reviewing and cleaning memory.

It is not the main product.

The main product is Claude Code integration.

Dashboard screens:

Project memory overview
Memory search
Memory detail
Source viewer
Edit memory
Delete memory
Open questions
Verified commands
Task summaries

The dashboard should let the user correct bad AI-generated memory.

This is important because automatically captured memory will never be perfect.


Search and Retrieval

For the MVP, NotNessie can start with keyword search.

A stronger version should use:

Keyword search
Semantic search
Memory type filters
File-path filters
Topic filters
Recency ranking
Pinned memory priority

Recommended storage options:

Fastest MVP:
SQLite with FTS5

Stronger backend demo:
PostgreSQL with pgvector

For an application demo, PostgreSQL + pgvector is more impressive, but SQLite is easier to ship quickly.


Database Schema

Simple MVP schema:

CREATE TABLE projects (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  root_path TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE TABLE memories (
  id TEXT PRIMARY KEY,
  project_id TEXT NOT NULL,
  type TEXT NOT NULL,
  title TEXT NOT NULL,
  summary TEXT NOT NULL,
  reasoning TEXT,
  topic TEXT,
  confidence REAL NOT NULL,
  tags TEXT NOT NULL,
  applies_to_files TEXT,
  is_pinned INTEGER DEFAULT 0,
  is_deleted INTEGER DEFAULT 0,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL,
  FOREIGN KEY(project_id) REFERENCES projects(id)
);

CREATE TABLE memory_sources (
  id TEXT PRIMARY KEY,
  memory_id TEXT NOT NULL,
  kind TEXT NOT NULL,
  session_id TEXT,
  task TEXT,
  file_paths TEXT,
  command TEXT,
  raw_reference TEXT,
  created_at TEXT NOT NULL,
  FOREIGN KEY(memory_id) REFERENCES memories(id)
);

CREATE TABLE verified_commands (
  id TEXT PRIMARY KEY,
  project_id TEXT NOT NULL,
  command TEXT NOT NULL,
  purpose TEXT,
  last_exit_code INTEGER,
  last_verified_at TEXT,
  created_at TEXT NOT NULL,
  FOREIGN KEY(project_id) REFERENCES projects(id)
);

CREATE TABLE task_summaries (
  id TEXT PRIMARY KEY,
  project_id TEXT NOT NULL,
  session_id TEXT,
  task TEXT NOT NULL,
  summary TEXT NOT NULL,
  files_changed TEXT,
  commands_run TEXT,
  outcome TEXT,
  created_at TEXT NOT NULL,
  FOREIGN KEY(project_id) REFERENCES projects(id)
);

Optional pgvector extension:

ALTER TABLE memories ADD COLUMN embedding vector;

Recommended Tech Stack

Core

TypeScript
Node.js
MCP SDK
SQLite or PostgreSQL

CLI

Node.js CLI
Commander.js or similar CLI framework

Dashboard

Next.js
React
Tailwind CSS
shadcn/ui
MVP: SQLite FTS5 or PostgreSQL full-text search
Better version: embeddings + pgvector

AI Usage

Use Claude Code heavily to build the project.
Use generated code, but review all architecture, storage, security, and MCP behavior manually.

AI-Assisted Development Approach

This project should be built heavily with AI assistance.

That is intentional.

The point is not to pretend every line was manually typed.

The point is to show practical AI-native engineering:

Use AI to build faster.
Use human judgment to control scope.
Use tests to verify behavior.
Use source-linked memory to avoid hallucinated project history.

AI can be used for:

Generating boilerplate
Creating MCP server skeleton
Writing TypeScript types
Drafting database migrations
Creating CLI commands
Writing hook scripts
Building dashboard components
Writing tests
Refactoring code
Writing documentation
Creating demo scripts

Human ownership remains necessary for:

Product scope
Architecture decisions
Security rules
Privacy limits
MCP tool design
Testing
Code review
Final demo quality

Privacy and Safety

NotNessie stores development memory, so it must avoid saving sensitive data.

Rules:

Do not save API keys.
Do not save tokens.
Do not save private keys.
Do not save database URLs.
Do not save credentials.
Do not save .env contents.
Do not save huge terminal outputs.
Do not save full source files unless explicitly requested.

Secret redaction should detect:

JWTs
API keys
Access tokens
Refresh tokens
Private keys
SSH keys
Database URLs
.env-style variables
Bearer tokens

If content looks sensitive, NotNessie should refuse to save it or redact it before storage.


MVP Non-Goals

The MVP will not include:

ChatGPT integration
Claude web import
Generic AI chat sync
Browser extension
Team accounts
Cloud dashboard
Enterprise admin panel
Billing
OAuth provider sync
Full prompt history storage
Full terminal recording
Automatic GitHub PR integration
Automatic issue tracker integration

These are outside the first demo.

The project should stay narrow and deeply integrated with Claude Code.


Development Plan

Phase 1 — Local Core

Build:

Project initialization
Local config
Local database
Memory CRUD
CLI status command

Commands:

notnessie init
notnessie status
notnessie memory list

Success condition:

A repository can be initialized and memory can be stored locally.

Phase 2 — MCP Server

Build the stdio MCP server.

Expose:

notnessie_get_project_context
notnessie_search_memory
notnessie_save_decision
notnessie_save_preference
notnessie_save_constraint
notnessie_save_verified_command
notnessie_save_task_summary

Success condition:

Claude Code can call NotNessie tools from inside a coding session.

Phase 3 — Claude Code Skill

Generate:

.claude/skills/notnessie/SKILL.md

The skill teaches Claude Code to:

Query context before non-trivial work.
Save important decisions after work.
Save corrections and constraints when the user gives them.
Avoid saving secrets.
Prefer current code over stale memory.

Success condition:

Claude Code understands when to use NotNessie.

Phase 4 — Hooks

Add hooks for:

SessionStart
Stop
PreCompact

MVP hook behavior:

SessionStart:
Check NotNessie status and prepare compact context.

Stop:
Save task summary if useful.

PreCompact:
Save a compact summary before context compaction.

Success condition:

NotNessie captures useful project context without requiring manual saving every time.

Phase 5 — Search and Context Packs

Add:

Keyword search
Task-aware ranking
Memory type filters
Context pack generation

Success condition:

A task query returns useful Claude Code context in under one second for a small local project.

Phase 6 — Dashboard

Add optional local dashboard.

Screens:

Memory list
Memory detail
Search
Open questions
Verified commands
Deleted memories

Success condition:

The user can review, edit, and delete saved memories.

Phase 7 — Demo Polish

Add:

Demo repository
Seed memories
README
Installation instructions
Demo script
Known limitations
Screenshots or short video

Success condition:

A reviewer can understand the product in 2–3 minutes.

Demo Script

This is NotNessie, a Claude Code-native project memory layer.

I start inside a repository and run `notnessie init`.

This creates the MCP config, Claude Code skill, hooks, and local project memory config.

Now Claude Code can access NotNessie tools.

I ask Claude Code to add refresh token rotation to the auth module.

Before editing, Claude queries NotNessie for relevant project context.

NotNessie returns previous decisions, constraints, verified commands, and open questions for this repository.

Claude now knows the project uses Fastify, PostgreSQL, Redis, and pnpm. It also knows not to edit generated files or change the public API response format.

Claude makes the code changes and runs the verified test command.

After the task, Claude saves a task summary, the files changed, the verified command, and any new implementation decisions.

In the dashboard, I can review the saved memories, edit incorrect ones, delete bad ones, and inspect where they came from.

The goal is simple: Claude Code should get better over time inside a repository instead of starting every task from zero.

Example Claude Code Workflow

User prompt:

Add refresh token rotation to the auth module.

Claude Code behavior with NotNessie:

1. Calls notnessie_get_project_context.
2. Receives auth-related project memory.
3. Finds previous decision: Redis stores refresh token metadata.
4. Finds constraint: public API response shape must not change.
5. Finds verified command: pnpm test auth.
6. Makes code changes.
7. Runs tests.
8. Saves task summary.
9. Saves new decision if token rotation strategy was finalized.

Success Criteria

The demo is successful if:

1. NotNessie can be initialized inside a repository.
2. Claude Code can connect to it through MCP.
3. Claude Code can retrieve project context before a task.
4. Claude Code can save decisions, constraints, commands, and task summaries.
5. Memories are structured, source-linked, editable, and deletable.
6. The system avoids saving secrets.
7. The demo clearly shows Claude Code improving over repeated sessions.

The strongest message of the project:

NotNessie turns Claude Code sessions into reusable project memory.

Final Scope

Build first:

Local CLI
Local database
MCP server
Claude Code skill
Claude Code hooks
Memory search
Context pack generation
Memory save tools
Simple dashboard

Avoid first:

ChatGPT integration
Generic chat import
Cloud sync
Team accounts
Browser extension
Enterprise features

NotNessie should be narrow, practical, and deeply integrated with Claude Code.