Agent-note is a skill-first, natural-language memory workflow for coding agents. You talk to your agent normally:
“Save this idea as a note.”
“Import this conversation.”
“What did we decide about the deployment plan?”
The agent discovers the shared agent-note skill, decides
what should be saved or retrieved, and uses a local command-line tool behind the
scenes for reliable storage, import, and search. You normally do not type
Agent-note commands yourself.
Notes remain plain Markdown under ~/.notes/, and semantic search runs locally
through FastEmbed.
Ask explicitly when information should become durable memory:
The skill turns the information into a complete, useful note with a clear title and a few retrieval-helpful tags. It preserves the meaning, reasons, constraints, and uncertainty that will matter when the note is found later instead of merely shortening the conversation.
Agent-note does not save casual chat without an explicit request.
The agent searches relevant notes, reads complete results when needed, and uses the newest closely relevant note as current context while retaining older notes as history.
Ask the agent to import the complete conversation or transcript:
The agent preserves the complete source once, creates a broad session handoff, then creates focused durable notes where useful. See Complete conversation import for the full workflow.
skills/agent-note/
SKILL.md model reasoning and workflow
references/durable-capture.md
references/conversation-import.md
scripts/agent-note symlink-safe local launcher
src/agent_note/
cli.py six JSON commands and stable exit codes
mcp_server.py local stdio MCP adapter, same six operations
service.py shared create/import/read result contracts
conversation_import.py exact raw transcript preservation
notes_store.py append-only Markdown storage and path guards
embeddings.py local hybrid search and embedding repair
The skill handles judgment: what is durable, how to preserve context and uncertainty, and which existing notes are relevant. After the agent invokes an operation, the local CLI and Python modules enforce the deterministic work: UTF-8 input, validation, configured paths, collision-safe filenames, tag normalization, raw separation, guarded reads, best-effort embeddings, search ranking, and structured results.
The default installation runs no background service or transport adapter. Each operation starts on demand and reads or writes the existing local files directly.
A local stdio MCP server exposes the same six operations (create, import, search, recent, tags, guarded read) to coding agents with MCP support. It spawns on demand over stdio: no ports, no tokens, no tunnel. Your OS user is the trust boundary, exactly like the CLI. It does not replace the skill or duplicate storage. See Local MCP server for setup.
Requirements:
- Python 3.12 or newer
- uv
- A shell-capable coding agent that supports repository-owned skills
Clone the repository and install its local environment:
git clone https://github.com/JLDynamics/Agent-note.git
cd Agent-note
uv syncKeep skills/agent-note as the one canonical skill folder.
Its launcher resolves the physical repository path with pwd -P, so a
user-level directory symlink works from unrelated projects without copying the
skill or globally installing the Python package.
After confirming the active agent runtime’s user skill directory, create a directory symlink. Common locally verified paths are:
AGENT_NOTE_REPO="/absolute/path/to/Agent-note"
# Codex
ln -s "$AGENT_NOTE_REPO/skills/agent-note" \
"$HOME/.codex/skills/agent-note"
# Claude Code
ln -s "$AGENT_NOTE_REPO/skills/agent-note" \
"$HOME/.claude/skills/agent-note"Then:
- Confirm the destination with
readlink. - Start a fresh agent session so skill discovery refreshes.
- Try a read-only natural-language request such as “What notes do I have about Agent-note?”
- If troubleshooting, run the linked
scripts/agent-note tagslauncher from an unrelated directory and confirm it returns JSON.
Skill discovery and refresh behavior are runtime-specific and should be live tested. Claude Desktop does not use a watched local skill folder; follow its supported skill installation flow instead of inventing a filesystem link.
The first embedding operation downloads roughly 90 MB and requires internet access. Later embedding and search operations use the downloaded model locally. To initialize it ahead of time:
uv run python -c "from agent_note.embeddings import embed_text; embed_text('warm up')"Conversation import is a model-plus-command workflow, but the agent performs the commands behind the scenes:
- The agent reads the complete source.
- It invokes
importonce. The command saves the exact supplied UTF-8 bytes under.raw/conversations/<conversation-id>/conversation.txtand writes separate metadata. - The agent identifies the genuinely durable ideas, decisions, preferences, actions or next steps, corrections, and unresolved questions that actually exist.
- It creates one broad session handoff first, using concise synthesis rather than merely shortening the transcript, and ends it with the exact returned source block.
- It searches for the main durable subjects.
- It creates only useful, non-duplicate focused notes for decisions, projects, preferences, actions, next actions, ideas, reviews, and other durable context. It preserves why ideas matter, the reasons for decisions, when preferences apply, and the uncertainty of assumptions, proposals, and unresolved questions. It skips casual chatter, does not label every note a summary, and ends every note with the same source block.
- It briefly checks that each identified important item appears in the broad handoff or a focused note, adding or expanding only what is missing. It does not copy every turn, force empty categories, or target a fixed note count.
- It searches for the broad handoff to verify retrieval.
Raw preservation alone is not a completed import. Raw files are not indexed:
they use .txt, and everything below .raw/ is excluded from normal note
indexing and guarded reads.
~/.notes/
.raw/
conversations/
conv-20260720T093000-a1b2c3d4/
conversation.txt # exact imported transcript
metadata.json # ID, dates, title, checksum
2026-07-04/
14-30-52.md # one note
14-30-52.embedding # local chunk vectors
Configure a different root with:
~/.notesrc:{"notes_folder": "~/MyNotes"}~/.noteswhen.notesrcis absent
Agent-note preserves this existing data format. No data migration is required.
Agent-note never edits or deletes an existing note. An update is a new note carrying the complete current context; the newest closely relevant note wins while older versions remain searchable history. “Append-only” describes Agent-note operations, not operating-system enforcement: files can still be changed manually.
Notes accept zero to eight tags. The skill uses only a few tags that materially help retrieval; eight is a limit, not a target. Storage normalizes them:
- lowercase
- spaces and underscores changed to hyphens
- duplicate and blank tags removed
- maximum 40 characters per tag
- maximum eight unique tags per note
For example, Memory System and conversation_import become memory-system
and conversation-import. Favor relevant topic tags and optionally one useful
kind tag such as idea, decision, preference, or session-handoff. Reuse
established tags when they fit, but do not force project or kind tags, add tags
for completeness, or build a complex taxonomy. Avoid duplicate, near-synonym,
and noisy tags. Existing category fields remain compatible and are read as
legacy tags without rewriting old notes.
Search combines local semantic similarity, keywords, and tag signals. Relevance stays primary. Results within 0.05 of one another are ordered newest-first, so a new version of the same idea wins without an unrelated recent note replacing a clearly relevant older result. Weak pure-semantic matches are omitted, and unreadable notes are skipped.
Embedding companions include a content hash and are replaced atomically. If a Markdown note changes manually or an embedding is missing or corrupt, the next search rebuilds it. A failed embedding never discards a successfully saved note.
Concurrent saves claim filenames with exclusive creation, so notes created in the same second receive distinct files rather than overwriting each other.
Agent-note is local-first, but it is not an encrypted vault:
- Notes, transcripts, metadata, and embedding companions are ordinary unencrypted files in the configured notes folder.
- Never commit or publish that folder. It may contain private conversations and personal information.
- FastEmbed downloads its model once, then embedding inference stays local. Note text and queries are not sent to a hosted embedding API.
- Behind-the-scenes command results can include note text, snippets, metadata, and absolute paths.
- Imported transcripts include a checksum for provenance, but Agent-note does not currently enforce it.
Most users can skip this section. The agent invokes these commands through the skill launcher. They remain useful for installation checks, debugging, automation, and development:
agent-note create --input PATH|- [--title TITLE] [--tag TAG ...]
agent-note import --input PATH|- [--original-date DATE] [--title TITLE]
agent-note search --query QUERY [--limit N] [--tag TAG ...]
agent-note recent [--days N] [--tag TAG ...]
agent-note tags
agent-note read --path NOTE_PATH
From the repository root, prefix a command with uv run. When using the linked
skills/agent-note/scripts/agent-note launcher, use the command arguments
directly.
create and import read complete UTF-8 bodies from a file or standard input;
they never require a body in a shell argument. Every result, including an
error, is JSON on standard output. Exit status 0 means success, 1 means an
operational failure, and 2 means invalid input or usage. Dependency
diagnostics may still appear on standard error.
agent-note-mcp speaks MCP over stdio using the same service functions as
the CLI. Each client spawns it on demand; nothing listens on the network.
Run uv sync once from the repository root, then register it with the
absolute repository path:
AGENT_NOTE_REPO="/absolute/path/to/Agent-note"Claude Code (project scope):
{
"mcpServers": {
"agent-note": {
"command": "uv",
"args": ["run", "--project", "/absolute/path/to/Agent-note", "agent-note-mcp"]
}
}
}Codex (~/.codex/config.toml):
[mcp_servers.agent-note]
command = "uv"
args = ["run", "--project", "/absolute/path/to/Agent-note", "agent-note-mcp"]Cursor (.cursor/mcp.json) and Claude Desktop (claude_desktop_config.json)
use the same mcpServers shape as the Claude Code snippet above.
Smoke-test the server directly:
printf '%s' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' | uv run agent-note-mcp | head -c 200uv lock --check
uv run --locked pytest -q
uv run pytest -m slow # real-model integration test, downloads the modelThe fast suite uses deterministic fake embeddings. See CONTRIBUTING.md for development guidance and SECURITY.md for private vulnerability reporting.
Agent-note is available under the MIT License.