Everkeep

io.github.st412m由 GitHub 账号 st412m 发布v1.1.0更新于 Nov 3, 2026

Your notes in one folder on your own server; AI clients read and edit it under write policies

概览

AI 生成的概览

Everkeep 让 AI 助手读写你自己机器上一个笔记与文档文件夹(vault),支持按目录设置写入策略,并以回收站代替删除。

可以做什么
  • 读取文件与文档:整份文件、行范围、一次多个文件、图片与音频、PDF 文本或整页渲染
  • 按内容正则搜索或按文件名查找,返回行号与版本标记
  • 写入与编辑:新建或覆盖文件、字面替换或按行编辑、创建目录、复制与移动
  • 把文件丢进所属目录的回收站,并可通过移动还原
  • 列出目录、带大小的列表、两层目录树、文件元数据与 vault 根目录
  • 以只读方式查看和查询 SQLite 数据库文件
适用场景
适合希望助手把工作笔记、决定和项目文件集中放在自己服务器的一个文件夹里、下次对话接着上次继续的场景;也适合把 PDF、Office 文档和邮件放进该文件夹后直接搜索并引用,而无需每次上传到对话中。
运行要求
作为本地进程运行,需要 vault 文件夹路径,由必填环境变量 EVERKEEP_VAULT 或 --vault 参数提供;可选 JSON 配置通过 EVERKEEP_CONFIG 指定。Windows 与 macOS 官方推荐用 Docker;无 Docker 的 Linux 需要 Node.js 22.17 或更高版本、poppler-utils 与 sqlite3。HTTP 客户端需要服务器生成的令牌,claude.ai 还需要公网 HTTPS 地址。
安装前请注意
令牌是唯一的钥匙,等同密码:持有者即可读取和修改笔记,任何离开本机的地址前都应加 TLS。未设置写入策略时,任何工具都可写入 vault 任意位置,策略需在服务器端配置。写入、移动和丢弃会改动真实文件,被丢弃的文件进入回收站且可能自动清理。文档提取的文本会缓存在 vault 之外,且策略只约束本服务器的工具,不影响其他写入该文件夹的程序。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Everkeep,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

Everkeep

Stop re-explaining yourself to your AI.

Everkeep keeps your notes, decisions and projects in one folder on your own server. Your AI assistant reads it when a chat starts and writes down what you worked out — so tomorrow's conversation picks up where today's ended. You decide what it may change; it can't delete or overwrite anything you haven't allowed.

Works with Claude and any MCP client · runs on Linux, Docker or Home Assistant

Your documents, too

Drop contracts, invoices, manuals, price lists and exported reports into the folder as they are — PDF, Word, Excel, PowerPoint, e-mails. Your AI reads them as text, searches all of them at once and tells you where it found the answer: "which contract has a 30-day payment term?" comes back with the file and the page. No uploading files into every chat, no copy-pasting; a new version of a file is read the next time it is needed. Scanned pages it looks at as images.

Files go into the folder by ordinary copying, like into any other folder: see putting your files in.

Quick start

This gets Everkeep running on your own computer with Docker and connects Claude to it. You need about ten minutes and no programming.

1. Install Docker. On Windows or macOS, install Docker Desktop and start it; wait until it says Docker is running. On Linux, install Docker Engine.

2. Start Everkeep. Open a terminal (on Windows: PowerShell; on macOS: Terminal) and paste the two lines for your system. The first creates the folder everkeep-notes in your home folder; that folder is where your notes will live. The second downloads Everkeep and starts it in the background; it starts again by itself after a reboot.

Windows (PowerShell):

powershell
mkdir $HOME\everkeep-notesdocker run -d --name everkeep --restart unless-stopped -p 127.0.0.1:3100:3100 -v "$HOME\everkeep-notes:/vault" -v everkeep-data:/data ghcr.io/st412m/everkeep:1.1.0

macOS or Linux:

sh
mkdir -p ~/everkeep-notesdocker run -d --name everkeep --restart unless-stopped -p 127.0.0.1:3100:3100 -v "$HOME/everkeep-notes:/vault" -v everkeep-data:/data ghcr.io/st412m/everkeep:1.1.0

On Linux the folder must be writable by user id 1000. If the command id -u prints a different number, follow Docker: who owns the folder instead.

3. Protect your notes. One more line, in the same terminal:

sh
docker exec everkeep everkeep policy set . --mode rev --trash

From now on Claude can create new files in the folder, but it can change an existing file only after reading it, so it never overwrites what it has not seen. Nothing is deleted: a file Claude discards goes into the folder .vault-trash inside everkeep-notes, and you can take it back from there.

4. Get your token. Everkeep made a secret token on its first start. Show it:

sh
docker exec everkeep everkeep token

It prints two lines. The first is the secret path for claude.ai, the second the header for other clients:

/private_<token>/mcpAuthorization: Bearer <token>

Treat both like a password: whoever has them can read and change your notes.

5. Connect Claude.

  • Claude Code on the same computer:

    sh
    claude mcp add --transport http everkeep http://127.0.0.1:3100/mcp --header "Authorization: Bearer <token>"
  • Claude Desktop on the same computer: add the block from Claude Desktop to its config file and restart it.

  • claude.ai in the browser, or the Claude apps: they connect from the internet, so Everkeep needs a public HTTPS address. Remote access shows two free ways, step by step. Then, in claude.ai → Settings → Connectors → Add custom connector, paste https://<your public address>/private_<token>/mcp.

6. Try it.

  • Ask Claude: "Use Everkeep to create a file about-me.md with what you know about my current projects." The file appears in your everkeep-notes folder.
  • Open the folder: on Windows, type explorer $HOME\everkeep-notes in the same PowerShell (or go to This PC → Users → your name → everkeep-notes); on macOS, type open ~/everkeep-notes in Terminal (or Finder → your home folder); on Linux, open your home folder in the file manager.
  • Copy a contract, an invoice or any PDF or Word file into it, by dragging or copy and paste, as into any folder. Everkeep sees it at once; nothing needs restarting. Folders inside it are fine and useful: contracts/, projects/….
  • Ask Claude: "Use Everkeep: what does the contract in my notes say about payment terms? Give the page."

To have Claude read your notes at the start of every chat, add a line like this in Settings → Account → Instructions for Claude, or to a project's instructions: "At the start of a chat, read /vault/about-me.md with Everkeep." Inside Docker your folder is /vault.

To change the rules for a folder, see Write policies.

What it is

Everkeep is an MCP server. MCP is the way AI clients such as Claude call tools on other machines. Everkeep's tools work on one directory tree, the vault: read, search, edit, move and discard files, read documents and PDFs, query SQLite databases read-only. Nothing outside the vault can be reached through it.

What the assistant may change is set per directory with write policies: a directory can be read-only, editable only by someone who has read the current version of a file, open to new files only, or free. There is no delete: discarding moves a file into a trash directory of its zone. The assistant cannot change the policies; you set them on the server.

It runs as one process, over HTTP for remote clients such as claude.ai and over stdio for local ones such as Claude Desktop.

What it looks like

The assistant lists a directory. The first line says what is allowed there:

text
Policy: overwrite=rev, trash=.vault-trash, auto-purge after 30 d — own marker (/vault/wiki/.vault-policy)
[FILE] .vault-policy[DIR] .vault-trash[FILE] decisions.md[FILE] todo.md

It tries to overwrite todo.md without having read it, and is refused:

text
Error: Refused — policy "overwrite: rev": changing an existing file requires its current rev, which is 5db20d56. Nothing was written. Repeat the call with rev: "5db20d56".

It searches, gets line numbers and the file's rev, and edits one line:

text
/vault/wiki/todo.md · rev 5db20d56 · 212 lines  148: - [ ] Check backup-rotation settings on the NAS
— 1 match(es) in 1 file(s) · scanned 37/37 files, 190 KB, 12 ms

Requirements

DockerDocker Desktop (Windows, macOS) or Docker Engine (Linux); images for amd64 and arm64 (Raspberry Pi 4/5)
Linux without DockerNode.js ≥ 22.17, poppler-utils (pdfinfo, pdftoppm), sqlite3
Home AssistantOS or Supervised, through the ha-filesystem-mcp app
Diskthe Docker image is about 340 MB; the npm package with its dependencies about 48 MB
For claude.aia public HTTPS address: see remote access

Installation

Docker

The image ghcr.io/st412m/everkeep runs everkeep serve on port 3100 as user id 1000, with the vault at /vault and its own state (token, document cache) in the volume /data. The Quick start shows docker run; compose.example.yaml does the same with Docker Compose. Folder ownership, updates and building the image yourself: installation.

Linux without Docker

Install poppler-utils and sqlite3 with your package manager, then run it with npx:

sh
npx --yes --package=everkeep everkeep serve --vault /home/me/notes

On first start it prints the token once; everkeep token shows it again. For a permanent everkeep command, a CPU without AVX (some Celeron, Atom and Pentium models) and a systemd service, see installation. Windows and macOS are not supported without Docker.

Home Assistant

Install the ha-filesystem-mcp app. It runs Everkeep with the vault under /media or /share and adds the Vault policies page to the sidebar.

Configuration

Settings come from flags, environment variables and an optional JSON file (EVERKEEP_CONFIG, else ~/.config/everkeep/config.json). The ones to know first:

SettingFlag / variableDefault
vault--vault, EVERKEEP_VAULTnone, required
host--host127.0.0.1
port--port3100
state_dirEVERKEEP_STATE_DIR~/.local/state/everkeep
token--token-file, EVERKEEP_TOKENgenerated into <state_dir>/token

everkeep check-config prints what is in force and checks the tools Everkeep needs. Every key, the token rules and the request log: configuration.

Connecting

  • claude.ai, Claude Desktop connectors, the Claude apps: Settings → Connectors → Add custom connector with https://<your-host>/private_<token>/mcp. The address must be public HTTPS: remote access.

  • Claude Code: over HTTP with the Bearer header, or on stdio:

    sh
    claude mcp add --transport stdio everkeep -- npx --yes --package=everkeep everkeep --vault /home/me/notes
  • Claude Desktop without a public address: Everkeep on stdio through Docker, see Claude Desktop.

  • Cursor and other clients: the URL http://127.0.0.1:3100/mcp (or your HTTPS address) with the header Authorization: Bearer <token>, see installation.

There is no OAuth: the token is the only key. A wrong path gets an empty 404, a wrong Bearer token 401.

Tools

20 tools. Parameters and return formats: tools.

Reading

  • read_text_file — a whole file, head/tail lines, or an offset/limit range with line count and rev; documents as numbered lines
  • read_multiple_files — several whole files in one response
  • read_media_file — image or audio as base64
  • read_pdf_text — text of a PDF or a page range, numbered like read_text_file
  • read_pdf_page — one PDF page rendered as JPEG

Searching

  • grep_files — regex search of file contents, documents included; returns path, rev, line count and matching lines
  • search_files — find files and directories by name

Writing

  • write_file — create or overwrite a file
  • edit_file — literal oldText replacement, or line-addressed edits guarded by rev
  • create_directory — create a directory and its parents
  • move_file — move or rename a file or directory; also restores from the trash
  • copy_file — copy a file; the destination follows the rules of write_file
  • trash_file — move a file into its zone's trash; there is no delete

Listing

  • list_directory — entries of one directory, after the policy line
  • list_directory_with_sizes — entries with file sizes, sorted by name or size
  • directory_tree — tree view, two levels deep
  • get_file_info — size, times and format, plus line count and rev for text files
  • list_allowed_directories — the vault root

SQLite (read-only)

  • sqlite_schema — DDL of every object, file pragmas, optional row counts
  • sqlite_query — one SELECT/WITH/VALUES/EXPLAIN statement, with a row limit

The search-then-edit workflow is in search and edit, SQLite in sqlite.

Write policies

With no policies, any tool may write anywhere in the vault. A policy is a small file .vault-policy in a directory; it covers the directory and everything below it. Set it on the server:

sh
everkeep policy set wiki --mode rev --trash --purge-days 30 --vault /home/me/noteseverkeep policy set raw --mode readonly --vault /home/me/notes
ModeEffect
readonlyno writes, edits, moves in or out, or discards
revnew files are free; changing, moving out or discarding an existing file needs its current rev
nevernew files only; existing files cannot be changed
freeno checks

With Docker, run the same commands inside the container: docker exec everkeep everkeep policy show. In the Home Assistant app, use the Vault policies page in the sidebar. The trash, auto-purge and what a broken marker does: write policies.

Documents and formats

read_text_file and grep_files read PDF, Word, Excel, PowerPoint, OpenDocument, EPUB, FB2, RTF, HTML and mail files as numbered lines with page, sheet and slide markers; grep_files reports where a match is (L8 (p.1), L2 (sheet Data)). A scanned PDF has no text; the answer says which pages to read as images with read_pdf_page. Documents are read-only. Extracted text is cached outside the vault. Formats, limits and the cache: documents.

Limitations

  • Linux only without Docker. Windows and macOS run it in Docker.
  • No OAuth. The token in the path or the Bearer header is the only key.
  • No delete. trash_file moves a file into a trash directory, and only in a zone that has one.
  • SQLite is read-only and will stay so.
  • Documents are read-only, and scans are not recognized as text (no OCR).
  • Policies stop Everkeep's tools only. Anything else that writes to the folder — you, a sync job, a file share — does not see them.
  • Clients cache the tool list. After an update that changes tools, an open conversation keeps the old list.

Troubleshooting

  • Claude shows no Everkeep tools. Check that the container runs (docker ps), that the token in the URL or header is the current one (everkeep token), and for claude.ai that the HTTPS address answers from outside.
  • Every write fails with EACCES. The vault folder is not writable by the user Everkeep runs as (user id 1000 in Docker).
  • 400 / 401 / 403 / 404 / 405 / 406. 401: wrong Bearer token. 404: wrong path or token in the path. 403: a Host or Origin that is neither local nor in allowed_hosts, on a server listening on 127.0.0.1. 405: not POST. 406: the Accept header lists neither JSON nor event streams. 400: bad JSON, an unsupported protocol version, or request headers that disagree with the body.
  • Every write is refused and listings print ⚠ Policy: BROKEN MARKER. A .vault-policy file is broken and locks its zone. Fix it with everkeep policy or by hand.

More: troubleshooting.

Security

  • The token is a password. It is generated by the server, at least 32 characters, never logged; put TLS in front of any address that leaves your machine.
  • Every path is confined to the vault, including through symlinks and on case-insensitive file systems.
  • On 127.0.0.1 (the default without Docker) requests whose Host or Origin is not local are refused, which stops websites in your browser from reaching it.
  • The token and the document cache live in the state directory, which must be outside the vault.
  • grep_files runs in a child process killed after 10 seconds; documents are extracted in worker threads with a timeout and a memory cap; SQLite runs sqlite3 -readonly -safe.

More: security.

Links

License

MIT — by st412m.

来源:README.md,提交 fdbf7b9

工具

20

grep_files

Search file contents

Search file CONTENTS by regex, recursively. Per file returns path, rev, line count, then matching line numbers with their text. Long lines are clipped around the match (max_line_length, default 200). Line numbers and rev feed straight into read_text_file offset/limit and edit_file line edits. Documents (PDF, Word, spreadsheets…) are searched in their extracted text: matches as L<n> (p.N / slide N / sheet Name), no rev; documents:false skips them. Other binaries and symlinks are skipped; output is capped and flags truncation when incomplete. To find files by name use search_files.

输入参数path必填contextexcludeincludepattern必填documentsignore_casemax_resultsmax_line_length

read_text_file

Read text file

Read one file. Whole file by default; head/tail = N lines from an edge; offset/limit = an arbitrary 1-based line range, which also reports total lines and rev (needed for edit_file line edits). Documents (PDF, DOCX, XLSX, PPTX, ODF, EPUB, MSG…) come as numbered lines with section markers, no rev, read-only; HTML, RTF, EML and FB2 read raw, extract:true gives their text. Several files at once: read_multiple_files; images and page images: read_media_file / read_pdf_page.

输入参数headpath必填taillimitoffsetextract

read_media_file

Read media file

Read an image or audio file as base64 with its MIME type. Not for PDF: one page as an image is read_pdf_page, the text is read_pdf_text.

输入参数path必填

read_pdf_page

Render PDF page

Render one PDF page (1-based) as JPEG. Prefer read_pdf_text unless layout or graphics matter.

输入参数page必填path必填

read_pdf_text

Extract PDF text

Text of a PDF, whole or a page range, as numbered lines with page markers (the same numbers as read_text_file). Much cheaper than page images — prefer it; for scans use read_pdf_page.

输入参数path必填last_pagefirst_page

sqlite_schema

Inspect SQLite schema

Inspect a SQLite database file: schema-neutral, no interpretation of the data. File type is decided by the first 16 bytes, not the extension. Returns table/index/view/trigger DDL from sqlite_master, the journal_mode/page_size/page_count/encoding/user_version/application_id PRAGMAs, the sqlite3 version, whether -wal/-shm siblings exist next to the ORIGINAL file, plus path/size/mtime (UTC and local with numeric offset). A database with no journal (or an empty leftover one) is opened in place and leaves no new files behind; one with a real -wal is read from a private copy instead, cleaned up after the call — wal_copy/wal_copy_ms in the response say whether that happened and how long it took. Either way nothing is ever left next to the original. counts=true adds COUNT(*) per table, off by default — it is a full scan and can take minutes on a large database. counts_timeout_ms is a PER-TABLE budget covering the whole call (spawning sqlite3 and opening the file, not just the COUNT itself) — on a large database file a very small budget can time out even a tiny table. A table that does not finish is null in counts; every such table is listed in counts_incomplete.tables with one shared counts_incomplete.note, not a message repeated per table. The rest of the schema is always returned in full. Call once without counts first, then again with counts only if row counts are actually needed — the DDL comes back in full either way, so a second call re-sends everything already read, which matters on a database with a hundred tables.

输入参数path必填countscounts_timeout_ms

sqlite_query

Query SQLite database

Run one read-only SQL statement on a SQLite file (sqlite3 -readonly -safe -json; ATTACH and other escapes are disabled). Must start with SELECT, WITH, VALUES, or EXPLAIN [QUERY PLAN] followed by one of those. Runs wrapped as SELECT * FROM (<sql>) LIMIT <limit+1>; truncated=true means more rows exist. ";" is allowed only inside string literals, quoted identifiers and comments, plus one trailing. Bind parameters (?, :x, @x, $x, #x) are rejected — write values as literals. EXPLAIN describes the wrapped statement. BLOBs are not converted — use hex(col) or length(col). A database with a -wal journal is read from a temporary copy (wal_copy in the response).

输入参数sql必填path必填limittimeout_ms

read_multiple_files

Read multiple files

Read several whole files at once (documents as numbered lines, as read_text_file; the trash is skipped). For a line range or rev use read_text_file.

输入参数paths必填

write_file

Write file

Create or overwrite a file with given content. In a zone with policy overwrite="rev", overwriting an EXISTING file requires its current rev (creating a new one does not); the refusal message carries the rev to use. For a change inside a file use edit_file. Document formats (PDF, DOCX…) are not overwritten.

输入参数revpath必填content必填

edit_file

Edit file

Edit a file. Two mutually exclusive edit shapes: {oldText,newText} literal replacement, or line edits (1-based). {startLine,endLine,newText} replaces the inclusive range; newText "" deletes, no trailing newline. Omitting endLine INSERTS before startLine instead of replacing, and startLine = lines+1 appends at EOF. Line edits require rev and are applied bottom-up in one atomic pass, so numbers from a single grep/read stay valid; a stale rev is rejected, never applied. Returns the new rev. dryRun shows the diff. In a zone with policy overwrite="rev" every edit needs rev, including {oldText}; in overwrite="never" zones editing is refused outright. To replace a whole file use write_file. Document formats are read-only.

输入参数revpath必填edits必填dryRun

create_directory

Create directory

Create a directory (and parents); an existing one is not an error. Refused where the zone policy forbids writing.

输入参数path必填

list_directory

List directory

List one directory; the first line is the policy in force. Sizes: list_directory_with_sizes; deeper levels: directory_tree.

输入参数path必填

list_directory_with_sizes

List directory with sizes

List a directory with file sizes, sorted by name or size. Without sizes: list_directory.

输入参数path必填sortBy

directory_tree

Show directory tree

Recursive tree view, 2 levels deep. One level: list_directory.

输入参数path必填

move_file

Move or rename

Move or rename a file or directory. Taking a file out of a zone with policy overwrite="rev" requires its current rev, exactly like overwriting it in place; directories are not moved out of a strict zone at all. Use trash_file, not this, to discard something; moving a file out of the trash restores it.

输入参数revsource必填destination必填

copy_file

Copy file

Copy a file to a new path inside the vault; the source stays. The destination follows the rules of write_file: overwriting an existing file needs its current rev in a zone with overwrite="rev" and is refused with overwrite="never"; read-only zones and the trash are refused. Directories are not copied.

输入参数revsource必填destination必填

trash_file

Move to trash

Discard a file by moving it into the trash of its own zone, keeping its relative path and adding an arrival timestamp to the name. There is no delete: this is the only way to remove something. Fails if the zone has no trash configured. In a zone with overwrite="rev" the current rev is required — you have to read a file before throwing it away. To restore, move_file it back out of the trash. A directory is not discarded as a unit: trash its files one by one.

输入参数revpath必填

search_files

Find files by name

Find files by NAME substring, recursively. For content use grep_files.

输入参数path必填pattern必填excludePatterns

get_file_info

Get file info

Metadata for a file or directory: size, times, format, plus line count and rev for text files (the rev that writes in a strict zone ask for). Content: read_text_file.

输入参数path必填

list_allowed_directories

List allowed directories

The vault root; every path must be inside it. Start here if the vault path is unknown.

无需输入参数。

版本历史

2
  1. v1.1.0最新Oct 29, 2026
  2. v1.0.0Oct 14, 2026

评分

已满足适用检查项的 90%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分
  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具必需15 分
  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分