Skip to main content

Persistent memory for AI agents — MCP-native, works with any LLM

Project description

Noshy Architecture Diagram

Noshy — Persistent Memory for AI Agents

ICM-compatible. MCP-native. Works with any LLM.

Noshy gives your AI agent real memory — not note-taking, not context stuffing, not a vector database you have to manage. Store facts, search across sessions, build knowledge graphs. It's what ICM wanted to be, re-built to work everywhere.

                     Noshy
          ┌───────────┼───────────┐
          │   MEMORIES            │   MEMOIRS
          │   (time-bound)        │   (permanent)
          │                       │
          │  ┌───┐ ┌───┐ ┌───┐    │   ┌───┐
          │  │bug│ │fix│ │pref│    │   │doc│
          │  └───┘ └───┘ └───┘    │   └───┘
          │    │       │     │     │
          │    └───┬───┘     │     │
          │  ┌─────┴─────┐   │     │
          │  │   GRAPH   │   │     │
          │  │  relations │   │     │
          │  └───────────┘   │     │
          └──────────────────┴─────┘
                    │
          ┌─────────┴──────────┐
          │   HYBRID SEARCH    │
          │  keyword+semantic  │
          │       +graph       │
          └────────────────────┘

Why Noshy

  • LLM-powered extraction — not regex. Uses any OpenAI-compatible API to extract structured facts from transcripts
  • Hybrid search — keyword + semantic + graph recall in one query
  • ICM compatible — import your existing ICM databases, uses the same schema
  • MCP native — works with Claude Code, Hermes, Codex, Copilot, and any MCP client
  • Any embedding provider — OpenAI, fastembed (local, free), or Hermes API server
  • Zero dependencies — core runs on Python stdlib. fastembed and OpenAI are optional
  • Single binary feel — one Python file does everything

Hermes vs Noshy

Hermes has built-in memory that persists across sessions, but it's small and limited to keyword matching. Noshy replaces that with a proper database that understands what you meant, not just what words you used.

What Noshy adds that Hermes doesn't have by default:

  • Semantic search — finds memories by meaning, not just keyword matching. Ask about "that proxy issue" and it finds the entry about SOCKS5 configuration even if the word "proxy" isn't in it.
  • Unbounded storage — Hermes caps memory at ~3,500 chars. Noshy stores unlimited entries in SQLite.
  • Richer memory types — memories (facts/decisions), memoirs (permanent knowledge), and concepts (related ideas linked together). Hermes just has flat text entries.
  • Graph relationships — links related memories so recalling one pulls up connected ones.
  • Session context injection — automatically surfaces what you were working on, recent decisions, and active projects when a session starts.
  • Decision timeline — chronological log of what was decided and why, so you can trace back.
  • Pattern detection — notices when the same solution keeps coming up and suggests turning it into a skill.
  • Weight decay — older, less-referenced memories fade in relevance automatically instead of cluttering results.

Quick Start

# Install from PyPI (recommended)
pip install noshy

# Start the HTTP server + dashboard
noshy serve
# → http://127.0.0.1:8720/

# Or run as an MCP stdio server
noshy mcp

Or install from source:

curl -fsSL https://raw.githubusercontent.com/noshkoto/Noshy/main/install.sh | sh

Usage

CLI

# Store a memory (optional --ttl, --importance auto, --project)
python3 server.py store "deploy-config" "Deploy uses Cloudflare Pages with GitHub Actions"

# Recall (add --json for machine output)
python3 server.py recall "deployment config"

# List projects with counts and last activity
python3 server.py projects

# Delete: by id, by topic, or wipe an entire project
python3 server.py delete --id 01J...
python3 server.py delete --topic "old-bug" --scope onboarding
python3 server.py delete --project staging --yes

# Maintenance
python3 server.py purge                  # delete expired
python3 server.py consolidate-clusters   # merge near-duplicates
python3 server.py sweep                  # purge + decay + consolidate

# Import from ICM
python3 server.py import /path/to/icm/memories.db

# Stats
python3 server.py stats

MCP Server (Claude Code, Hermes, Codex, Copilot)

Add to your MCP client config:

Claude Code (~/.claude/mcp_servers.json):

{
  "mcpServers": {
    "noshy": {
      "command": "python3",
      "args": ["/path/to/noshy/server.py", "mcp"],
      "env": {
        "NOSHY_EMBED_PROVIDER": "openai",
        "OPENAI_API_KEY": "sk-..."
      }
    }
  }
}

Hermes (config.yaml):

mcp_servers:
  noshy:
    command: "python3"
    args: ["/path/to/noshy/server.py", "mcp"]
    env:
      NOSHY_EMBED_PROVIDER: "openai"
      OPENAI_API_KEY: "sk-..."

Codex CLI (~/.codex/mcp.json):

{
  "mcpServers": {
    "noshy": {
      "command": "python3",
      "args": ["/path/to/noshy/server.py", "mcp"]
    }
  }
}

MCP Tools

Tool What it does
noshy_store_memory Remember a fact, decision, or preference (optional ttl_seconds to auto-expire)
noshy_store_memoir Store permanent knowledge (docs, reference)
noshy_recall Search memories (keyword, semantic, hybrid) — also surfaces matching memoirs
noshy_extract_session LLM-powered extraction from conversation transcripts
noshy_stream_extract Incremental extraction for very long transcripts (chunked + overlap)
noshy_consolidate Merge related memories on a topic
noshy_delete Remove a memory by id, or all memories under a topic
noshy_feedback Rate a memory +1/-1 to influence how long it survives
noshy_list_projects List every project with per-project counts and last activity
noshy_delete_project Wipe all memories and memoirs for a project (irreversible)
noshy_predict_importance LLM-classify a candidate fact without storing it
noshy_find_clusters Preview clusters of semantically near-duplicate memories
noshy_consolidate_clusters Auto-merge those clusters in one pass
noshy_get_stats Database overview

HTTP API

# Store
curl -X POST http://127.0.0.1:8720/tools/call \
  -H 'Content-Type: application/json' \
  -d '{"name":"noshy_store_memory","arguments":{"topic":"my-topic","summary":"What to remember"}}'

# Recall
curl -X POST http://127.0.0.1:8720/tools/call \
  -H 'Content-Type: application/json' \
  -d '{"name":"noshy_recall","arguments":{"query":"search keywords"}}'

# Stats
curl http://127.0.0.1:8720/stats

# Recent memories (JSON)
curl 'http://127.0.0.1:8720/memories?limit=25'

Web Dashboard

The HTTP server also serves a zero-dependency web dashboard. Start the server and open the root URL in a browser:

python3 server.py http
# then visit http://127.0.0.1:8720/

Dashboard features:

  • Project picker — filter recent memories and search by project
  • Hybrid search — keyword + semantic + graph in one query box; memoirs included
  • Cluster view — surface groups of near-duplicate memories and merge them in one click
  • Inline delete — hover a card, click × to remove it (with confirmation)
  • Dark / light theme — auto-detected, manually toggleable, persisted to localStorage

Python API

For scripts and apps, Noshy ships a small Python API with decorators that make any function self-remembering:

import noshy

@noshy.remember(topic="deploy", importance="high")
def deploy(env):
    return f"deployed to {env}"

deploy("prod")                  # auto-stores: deploy -> 'deployed to prod'

# Scope memories to a project (and inherit tags) for a block of code
with noshy.session(project="checkout-bugfix", tags=["sprint-23"]):
    do_work()                   # every @remember inside picks up the project

noshy.recall("deploy")          # hybrid search returns matching memories

Useful keyword arguments on @noshy.remember:

  • importance="auto" — let the LLM classify each memory (critical/high/medium/low)
  • on_error=True (default) — exceptions are stored as high-importance memories
  • capture_args=True — include arg names in the summary; arguments whose names look like secrets (password, token, api_key, …) are auto-redacted
  • skip_if=lambda r: r is None — don't store certain return values
  • ttl_seconds=… — auto-expire after N seconds

For long-running sessions, noshy.extractor.stream_extract(chunks) yields memories incrementally as transcript chunks arrive.

Embedding Providers

Noshy auto-detects the best available embedding provider. Set NOSHY_EMBED_PROVIDER to override:

Provider Env Var API Key Quality
OpenAI NOSHY_EMBED_PROVIDER=openai OPENAI_API_KEY Best
fastembed NOSHY_EMBED_PROVIDER=fastembed None (local) Good
Hermes API auto-detected API_SERVER_KEY Varies
None No embedding None Keyword only
# With OpenAI
export OPENAI_API_KEY="sk-..."
python3 server.py http

# With free local embeddings
pip install fastembed
python3 server.py http

# Keyword-only (no embeddings)
NOSHY_EMBED_PROVIDER=none python3 server.py http

Platform Setup

macOS

# Install Python 3.10+ if needed
brew install python@3.12

# Install Noshy
curl -fsSL https://raw.githubusercontent.com/noshkoto/Noshy/main/install.sh | sh

# Optional: local embeddings
pip3 install fastembed

Linux

sudo apt install python3   # Debian/Ubuntu
sudo dnf install python3    # Fedora

curl -fsSL https://raw.githubusercontent.com/noshkoto/Noshy/main/install.sh | sh

Windows

# Install Python from python.org (check "Add to PATH")

# Download Noshy
Invoke-WebRequest -Uri https://github.com/noshkoto/Noshy/archive/refs/heads/main.zip -OutFile noshy.zip
Expand-Archive noshy.zip -DestinationPath $env:USERPROFILE\.noshy
Rename-Item $env:USERPROFILE\.noshy\Noshy-main $env:USERPROFILE\.noshy\src

# Run
python $env:USERPROFILE\.noshy\src\server.py http

Docker

# Build the image from the included Dockerfile
docker build -t noshy .

# Run it (data persists in a named volume)
docker run -d --name noshy \
  -p 8720:8720 \
  -v noshy-data:/data \
  -e OPENAI_API_KEY=sk-... \
  noshy

# Or with HTTP auth enabled
docker run -d --name noshy \
  -p 8720:8720 \
  -v noshy-data:/data \
  -e NOSHY_HTTP_TOKEN=$(openssl rand -hex 32) \
  noshy

# Optional build flags
docker build --build-arg WITH_FASTEMBED=1 -t noshy .   # bake local embeddings
docker build --build-arg WITH_SQLITE_VEC=0 -t noshy .  # skip the vec extension

The image runs as a non-root user, exposes a /health endpoint, and uses /data as a persistent volume.

HTTP authentication

By default the HTTP server is unauthenticated and binds to 127.0.0.1 only. To expose it on a network or behind a proxy, set a bearer token:

export NOSHY_HTTP_TOKEN="$(openssl rand -hex 32)"
python3 server.py serve --host 0.0.0.0

Clients must then send Authorization: Bearer <token> on every request. The /health endpoint and the dashboard HTML at / stay public so probes and human visitors still work.

Configuration

Env Variable Default Description
NOSHY_DB ~/.noshy/memories.db Database path
NOSHY_EMBED_PROVIDER auto openai, fastembed, hermes, or none
NOSHY_EMBED_MODEL provider default Embedding model name
NOSHY_EMBED_API_BASE provider default Embedding API URL
NOSHY_EMBED_API_KEY OPENAI_API_KEY Embedding API key
NOSHY_API_BASE http://127.0.0.1:8642/v1 LLM API for extraction
NOSHY_API_KEY API_SERVER_KEY LLM API key
NOSHY_MODEL hermes-agent Model for extraction
NOSHY_HTTP_TOKEN unset If set, all HTTP routes require Authorization: Bearer <token> (except /health and /)

Architecture

┌─────────────────────────────────────────┐
│              Noshy MCP Server            │
│  ┌──────────┐ ┌────────┐ ┌───────────┐  │
│  │Extractor │ │ Store  │ │  Embedder │  │
│  │(LLM API) │ │(SQLite)│ │(OpenAI/   │  │
│  │          │ │        │ │ fastembed) │  │
│  └──────────┘ └────────┘ └───────────┘  │
│         │          │           │         │
│         └──────────┼───────────┘         │
│                    │                     │
│        ┌───────────┴────────┐            │
│        │   Hybrid Search    │            │
│        │ keyword semantic   │            │
│        │      + graph       │            │
│        └────────────────────┘            │
│                    │                     │
│           ┌────────┴───────┐             │
│           │  MCP / HTTP    │             │
│           │  (stdio+API)   │             │
│           └────────────────┘             │
└─────────────────────────────────────────┘

Import from ICM

# Import memories from an existing ICM database
python3 server.py import ~/.config/icm/memories.db

# Verify
python3 server.py stats

The schema is compatible — memories, memoirs, concepts, and metadata all transfer. Graph edges and feedback are preserved when available.

Comparison

ICM Noshy
Extraction Rule-based regex LLM-powered (any provider)
Search Keyword + vector Keyword + semantic + graph
Embeddings fastembed only OpenAI, fastembed, Hermes, none
Relationships Memoir categories only Full graph with weighted edges
Consolidation Manual LLM-assisted auto-merge
Deployment Rust binary (compile) Python stdlib (zero-deps core)
MCP Yes Yes
API MCP only MCP + HTTP + Python import
ICM import N/A Built-in

Roadmap

  • Web dashboard
  • Semantic search over memoirs (auto-embedded on store)
  • Automatic, importance-aware memory decay
  • Consolidation that prunes merged duplicates
  • Python decorator for automatic function memory (@noshy.remember)
  • Memory importance prediction (importance="auto")
  • Streaming extraction (extractor.stream_extract)
  • Project isolation (list_projects / delete_project)
  • Graph-based memory consolidation (find_clusters / consolidate_clusters)
  • HTTP bearer-token auth (NOSHY_HTTP_TOKEN)
  • Real Dockerfile (multi-stage, non-root, healthcheck)
  • Integration test suite (pytest tests/)
  • PyPI release (pip install noshy)
  • Streaming extraction MCP tool (noshy_stream_extract)
  • Dashboard polish (project picker, cluster view, inline delete, theme toggle)
  • Per-user database isolation (multi-tenant — one DB per token)

License

Apache 2.0 — same as ICM. Built as a drop-in improvement.


"Your agent shouldn't forget what you fixed last week."

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

noshy-0.3.0.tar.gz (79.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

noshy-0.3.0-py3-none-any.whl (68.0 kB view details)

Uploaded Python 3

File details

Details for the file noshy-0.3.0.tar.gz.

File metadata

  • Download URL: noshy-0.3.0.tar.gz
  • Upload date:
  • Size: 79.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for noshy-0.3.0.tar.gz
Algorithm Hash digest
SHA256 e8a87f5f47ec7c26b65a54b72c962aa2c73b7ab8722879e014c89ba661fdb2ee
MD5 313b84f98a653531df78f535af120e48
BLAKE2b-256 7f5088fcdc5a68d2262e68df8aeea0315763b18565bbd392665fde307afd0a8b

See more details on using hashes here.

Provenance

The following attestation bundles were made for noshy-0.3.0.tar.gz:

Publisher: release.yml on Noshkoto/Noshy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file noshy-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: noshy-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 68.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for noshy-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ed2e744f4a3f3646e5f2f7737490e3791e55ce5b9b228e525b61d01798dbbc9a
MD5 63a912502d113810412357558c2e27d9
BLAKE2b-256 45c7e9158d28eb5ec01df89b234b9adde7474c5d57ecd801dfdaf1e4d0970219

See more details on using hashes here.

Provenance

The following attestation bundles were made for noshy-0.3.0-py3-none-any.whl:

Publisher: release.yml on Noshkoto/Noshy

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page