Your agent has amnesia. Noshy fixes that. Persistent memory for AI agents — LLM extraction, hybrid search, zero deps.
SaferSkills independently audited Noshy (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.

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 │
└────────────────────┘~/.noshy/config.toml with env var overrides, no code changes neededNOSHY_LOG_FILE or run in a container to get ~/.noshy/noshy.log (5MB x 3 rotation)contradicts edges so future recalls warn about themHermes 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:
# 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 mcpOr install from source:
curl -fsSL https://raw.githubusercontent.com/noshkoto/Noshy/main/install.sh | sh# 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 find-contradictions # detect + link conflicting memory pairs
python3 server.py sweep # purge + decay + consolidate + drain queue
# Async extraction queue (hand off long transcripts without blocking on the LLM)
python3 server.py queue --file session.txt --session-id sess-2026-06-18
python3 server.py process-queue --limit 10
# Import from ICM
python3 server.py import /path/to/icm/memories.db
# Stats
python3 server.py statsAdd 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"]
}
}
}| 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_session_context | Generate context for a new session — critical memories, recent decisions, active work. Call at session start |
noshy_decision_timeline | Chronological timeline of decisions, fixes, and resolutions. Answer "what did we decide about X?" |
noshy_detect_patterns | Find repeated solutions across sessions — candidates for creating reusable skills |
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_find_contradictions | Detect (and link) pairs of memories that assert conflicting facts |
noshy_queue_extraction | Hand off a transcript for later LLM extraction without blocking |
noshy_process_queue | Drain queued extractions through the LLM |
noshy_get_stats | Database overview |
# 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'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:
localStorage?page=1&limit=25 for large databasesWhen NOSHY_HTTP_TOKEN is set, the dashboard shows a token prompt modal on first load. The token persists in localStorage across reloads. A "Forget" button clears it. API routes enforce auth; / and /health stay public.
Noshy can automatically extract memories when a session ends. Drop the hook into your Hermes workflow or call it from any MCP client:
from hooks import on_session_end
result = on_session_end(transcript, project="my-project", max_memories=8)
# → {"extracted": 5, "ids": [...], "concepts": ["deploy", "ci"]}The hook skips transcripts shorter than 100 characters and returns structured results with extracted memory IDs and discovered concepts.
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 memoriesUseful 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 memoriescapture_args=True — include arg names in the summary; arguments whosenames look like secrets (password, token, api_key, ...) are auto-redacted
skip_if=lambda r: r is None — don't store certain return valuesttl_seconds=... — auto-expire after N secondsFor long-running sessions, noshy.extractor.stream_extract(chunks) yields memories incrementally as transcript chunks arrive.
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# Install Python 3.10+ if needed
brew install [email protected]
# Install Noshy
curl -fsSL https://raw.githubusercontent.com/noshkoto/Noshy/main/install.sh | sh
# Optional: local embeddings
pip3 install fastembedsudo apt install python3 # Debian/Ubuntu
sudo dnf install python3 # Fedora
curl -fsSL https://raw.githubusercontent.com/noshkoto/Noshy/main/install.sh | sh# 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# 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 extensionThe image runs as a non-root user, exposes a /health endpoint, and uses /data as a persistent volume.
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.0Clients 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.
Noshy supports two configuration methods. Environment variables always take precedence over the config file.
Create ~/.noshy/config.toml (or set NOSHY_CONFIG to a custom path):
[noshy]
db-path = "~/.noshy/memories.db"
embed-provider = "openai"
embed-model = ""
api-base = "http://127.0.0.1:8642/v1"
model = "hermes-agent"
http-host = "127.0.0.1"
http-port = 8720| Env Variable | Default | Description |
|---|---|---|
NOSHY_CONFIG | ~/.noshy/config.toml | Path to config file |
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 *** (except /health and /`) |
NOSHY_LOG_FILE | _unset_ | If set (or stderr is not a tty), rotating logs go to ~/.noshy/noshy.log (5MB x 3) |
Noshy auto-migrates the database schema on startup (v1 through v4). No manual steps required. New columns are added transparently; existing data is preserved.
┌─────────────────────────────────────────┐
│ Noshy MCP Server │
│ ┌──────────┐ ┌────────┐ ┌───────────┐ │
│ │Extractor │ │ Store │ │ Embedder │ │
│ │(LLM API) │ │(SQLite)│ │(OpenAI/ │ │
│ │ + retry │ │ +migrate│ │ fastembed) │ │
│ │ │ │ factory│ │ +numpy cos│ │
│ └──────────┘ └────────┘ └───────────┘ │
│ │ │ │ │
│ └──────────┼───────────┘ │
│ │ │
│ ┌───────────┴────────┐ │
│ │ Hybrid Search │ │
│ │ keyword semantic │ │
│ │ + graph │ │
│ └────────────────────┘ │
│ │ │
│ ┌────────┴───────┐ │
│ │ MCP / HTTP │ │
│ │ (stdio+API) │ │
│ └────────────────┘ │
│ │ │
│ ┌────────┴───────┐ │
│ │ Session Hooks │ │
│ │ (auto-extract)│ │
│ └────────────────┘ │
└─────────────────────────────────────────┘# Import memories from an existing ICM database
python3 server.py import ~/.config/icm/memories.db
# Verify
python3 server.py statsThe schema is compatible — memories, memoirs, concepts, and metadata all transfer. Graph edges and feedback are preserved when available.
| 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 | |
| Config | Env vars only | TOML file + env var overrides | |
| Lifecycle | Manual process management | Graceful shutdown, auto-migration, retry | |
| Cosine similarity | Pure Python | Numpy-vectorized (~50x faster), pure-Python fallback | |
| Contradiction detection | None | LLM-powered conflict scan with persistent contradicts edges | |
| Extraction queue | Synchronous only | Async queue with background drain | |
| Logs | stdout only | Rotating file logs (5MB x 3) | |
| Dashboard auth | None | Token prompt modal, localStorage persistence |
@noshy.remember)importance="auto")extractor.stream_extract)list_projects / delete_project)find_clusters / consolidate_clusters)NOSHY_HTTP_TOKEN)pytest tests/)pip install noshy)noshy_stream_extract)~/.noshy/config.toml)NOSHY_LOG_FILE)noshy_find_contradictions + contradicts edges on recall)noshy_queue_extraction / noshy_process_queue)Apache 2.0 — same as ICM. Built as a drop-in improvement.
"Your agent shouldn't forget what you fixed last week."
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.