settings — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited settings (Hook) 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.
[!WARNING] This is a personal project. I maintain it for my own use and share it because others might find it useful. Feature PRs are unlikely to be merged — if you have an idea, start a discussion first. Fork freely — it's MIT licensed.
AI-accessible knowledge you actually own. Plain markdown files on your disk, searchable by AI via MCP.
Your notes live on your disk as plain markdown with YAML frontmatter — readable without mor, portable to any tool, git-syncable across machines. The MCP server gives AI assistants (Claude Code, Claude Desktop, Cursor, etc.) persistent memory that survives context windows. You also get a CLI and HTTP API.
npm install -g morRequires Node.js 20+.
# Add notes
echo "Always use snake_case for Python variables" | mor add -t "Python naming"
mor add notes.md -t "Meeting notes" --tags "meeting,project-x"
mor add https://raw.githubusercontent.com/owner/repo/main/config.ts
# Search (FTS5 — tokenized, stemmed)
mor find python naming
# Grep (literal substring or regex)
mor grep snake_case
mor grep -i todo
mor grep -E "async\s+function"
mor grep -w Beer -n -C 2
# Read, edit, copy, remove
mor cat python naming
mor edit python naming
mor cp -o ./out.md python naming
mor rm python naming
# List
mor ls
mor ls -l| Command | Description | |
|---|---|---|
find <query> | Full-text search (--limit, -s threshold, --json) | |
grep <pattern> | Substring or regex search (-i, -E regex, -w word, -n line numbers, -l files only, -A/-B/-C context) | |
| `add [file\ | url]` | Add from file, URL, stdin, or $EDITOR (-t title, -d description, --tags, --type) |
cat <query> | Print content (--raw for frontmatter, --links for cross-references) | |
cp <query...> | Copy content to file (-o <dest>) | |
edit <query> | Open in $EDITOR (--raw to edit frontmatter) | |
update <query> | Update metadata or content (-t title, -d description, --tags, --type, --content-from) | |
patch <query> | Apply a str_replace patch to a note's content (--old, --new) | |
rm <query> | Remove a note | |
links [query] | Show cross-references for a note (--broken to find dangling links) | |
ls | List all (--limit, -l long, --tags, --types) | |
sync | Pull, commit, and push the notes folder via git | |
reindex | Rebuild search index | |
import <dir> | Import .md files from a directory | |
mcp | Start MCP server (stdio) | |
serve | Start HTTP server (-p port, -H host, --token, --mcp) | |
login | Authenticate with a remote server via OAuth (-s server URL) |
Queries resolve in order: full UUID, UUID prefix (8+ chars), filename, FTS search. Multi-word queries don't need quoting — options go before the query: mor find --limit 5 python naming.
find, grep, and ls support shared filters: --type, --tag, --repo, --ext (all support glob patterns).
Add to your Claude Code or Claude Desktop config:
{
"mcpServers": {
"mor": {
"command": "mor",
"args": ["mcp"]
}
}
}Tools: notes_search, notes_read, notes_create, notes_update, notes_patch, notes_remove, notes_list, notes_grep.
To make sure Claude Code checks mor first when you ask it to recall something, add this to ~/.claude/CLAUDE.md:
## Notes
When the user asks to recall, find, check, or reuse something they previously saved
or remembered — use the `mor` MCP server tools (`notes_search`, `notes_read`,
`notes_list`). This is the user's primary note store containing code snippets,
files, and reference notes. Always check mor before saying something wasn't found.Run the server on one machine, access from anywhere:
# Server
mor serve --port 7677 --token mypassphrase --mcpPoint your MCP client at the server URL — no secret in the config:
{
"mcpServers": {
"mor": {
"type": "url",
"url": "http://mybox.tail1234.ts.net:7677/mcp"
}
}
}The client discovers auth via WWW-Authenticate → OAuth metadata → browser passphrase flow, all automatic.
# OAuth login — saves server URL to config and credentials to credentials.json
mor login -s http://mybox.tail1234.ts.net:7677
# All commands now proxy to the remote server
mor find "python naming"Or configure a direct token instead:
// ~/.config/mor/config.json
{
"server": {
"url": "http://mybox.tail1234.ts.net:7677",
"token": "mypassphrase",
},
}OAuth tokens auto-refresh on expiry.
When --token is set, all routes require auth. Two methods work everywhere:
Authorization: Bearer <passphrase> or ?token=<passphrase>mor login or MCP client auto-discovery)Unauthenticated requests get a 401 with a WWW-Authenticate header pointing to the OAuth discovery endpoint.
| Method | Path | Description |
|---|---|---|
GET | /health | Health check |
GET | /notes?limit=N&offset=N | List all |
GET | /notes/search?q=...&limit=N&offset=N | FTS search |
GET | /notes/grep?q=...&limit=N&offset=N&ignoreCase=1®ex=1 | Substring or regex search |
GET | /notes/:query | Read one |
GET | /notes/:query/links | Get forward and backlinks |
POST | /notes | Create ({title, content, description?, tags?, type?, repository?}) |
PUT | /notes/:query | Update ({title?, description?, content?, tags?, type?}) |
POST | /notes/:query/patch | Patch content ({old_str, new_str}) |
DELETE | /notes/:query | Remove |
POST | /reindex | Rebuild the search index |
POST | /sync | Git pull, commit, push |
POST | /mcp | MCP protocol (streamable HTTP) |
Optionally augment FTS search with vector similarity. Configure in config.json:
{
"embedding": {
"provider": "openai",
"model": "text-embedding-3-small",
"dimensions": 1536
}
}Providers: openai (or compatible API via baseUrl), azure-openai, ollama. Run mor reindex after configuring.
Azure OpenAI uses AZURE_OPENAI_API_KEY (or apiKey in config) and requires a deployment name (defaults to model name).
Notes are markdown files with YAML frontmatter, split across XDG directories. Set MOR_HOME for a single flat directory.
~/.config/mor/ # config
config.json
~/.local/share/mor/ # data
notes/
python-naming-a1b2.md
meeting-notes-c3d4.md
~/.local/state/mor/ # state
index.db # search index
credentials.json # OAuth tokens (mor login)
oauth.db # OAuth server tokensFiles are human-readable and git-friendly. Use mor sync to pull, commit, and push if the notes folder is a git repo. Enable autosync to sync automatically after every add, update, or remove:
{
"autosync": true
}MIT
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.