The Headless Client
The Headless Client is EtherPK with no editor: a small program, @appsoftwareltd/etherpk-mcp,
that gives an AI agent one of your knowledge graphs over MCP, running on the same computer as
the agent. The agent can search your notes by words or by meaning, follow links, list tasks,
read and edit documents without breaking EtherPK's format, add images and files, and publish a
site. It needs Node.js 22 or later.
It serves a synced graph, by signing in as one of your devices and keeping the graph in sync, or a local graph folder, with no sign-in at all. The agent gets the same tools either way. Protected documents are listed by name only and never served.
Set up: a synced graph
Open the graph in EtherPK, open Settings > Agents, and copy the two commands it shows with your server and graph filled in.
-
Sign the computer in, once per Sync Server:
npx @appsoftwareltd/etherpk-mcp login --sync-server https://sync.etherpk.comThat is the managed service's server; give your own server's address if you self-host. It asks for a Personal Access Token: make one at your Sync Server's portal under Access tokens (the Agents tab links straight to it, and so does the account menu in EtherPK). It then shows a short code. Open EtherPK in a browser where you are signed in and your keys are unlocked; a prompt appears with a code; confirm it matches and the computer holds your keys from then on. This is the same approval as adding a phone (Recovery Code And Device Approval), and nothing secret is typed into the terminal. To use your Recovery Code instead, on a server you reach over SSH say, press
rwhile it is waiting, or add--recovery-code. When it is done it lists the graphs it can see, by name and id. -
Tell the agent about the graph. Pick your agent in the Agents tab and copy the command it shows; for Claude Code it is:
claude mcp add etherpk -- npx @appsoftwareltd/etherpk-mcp serve --sync-server https://sync.etherpk.com --graph <graph id>Codex has the same shape; Cursor and other tools take a small block of MCP JSON, which the tab shows instead. One Headless Client serves one graph; to give an agent two graphs, add it twice under two names.
When the agent starts, the Headless Client connects, catches up with the graph and stays connected while the agent works. Other members of a shared graph see it as a device called "Agent on <your computer's name>".
One computer can be signed in to several servers, your own beside the managed service say. Run
login once per server; --sync-server then says which one a command means, and can be left
off while only one is signed in.
Set up: a local graph folder
claude mcp add etherpk -- npx @appsoftwareltd/etherpk-mcp serve --folder /path/to/your/notes
The folder must already be an EtherPK graph: open it in EtherPK once. The Agents tab shows the command with your folder's path once you have recorded the path on the General tab. Edits made in an editor, or by the agent writing files directly, are picked up before the next tool call. Nothing is written into the folder by the Headless Client; its index lives under its cache directory.
What the agent can do
| It can | It cannot |
|---|---|
| List every page and journal entry, with aliases, and the journal for a range of days | Read or change a protected document: those are listed by name only and every attempt is refused, images and files included |
| Read a document (its text, and its frontmatter as data), several at once; search by words or, once set up, by meaning; follow backlinks; list tasks and their tags | Delete a document; do that in EtherPK |
| Edit a document by replacing an exact piece of text, so its change merges with anyone typing elsewhere on the page; tick, prioritise and date a task | Replace a whole page in one go |
Append to a page or to a day's journal entry (creating the entry), create new pages, set frontmatter such as public, publications and date, set aliases |
Change a page's title through its frontmatter: that is a rename |
| Rename a page or concept: scoped pages come along and every link is rewritten, or the old name kept as an alias if you ask; a merge needs the agent to confirm it | Rewrite links inside a protected document, which it cannot see |
| Add an image or file and get the markdown to paste; read a file a page references back to disk | See an image or file that no readable document references, or list orphaned assets |
| List, create and change publications; publish one into the folder you set; read the report | Choose or change the publish folder, or put the site online |
| Copy a publication's theme into the graph, read its files out to disk, edit them, write them back, preview the result and publish | Edit a bundled theme in place; it copies it first, as Customise theme does |
| Reach any graph you are not a member of, or any other account; the server checks that on every request |
Edits arrive in your open tabs the way another member's typing does, and an agent's four-space bullets are put on EtherPK's two-space grid as they land.
No skill or further setup is needed: the Headless Client describes its tools and your graph to
the agent, so asking about your notes is enough for Claude Code to reach for them. To make that a
rule rather than a good guess, add one line to your CLAUDE.md: "My notes live in EtherPK; use
the etherpk MCP tools for anything I've written down, and search in semantic mode for
questions."
Search by meaning
Out of the box the agent's search matches words. Asked "what did I decide about keeping old uploads?", it guesses keywords, gets nothing, and reports that there is no such note. You would have remembered the page was called Asset Retention; it cannot.
Semantic search finds notes by what they mean: "when do I have to pay my taxes" finds the page that says "the return is due 31 January" though the two share no words. A small language model on the agent's computer turns each passage of your notes into numbers representing its meaning and compares those against the question. Nothing is generated or summarised: the agent gets your own passages, best match first, each with the page, the headings above it and its lines, so it can say where an answer came from. Nothing leaves the computer.
It is off until you set it up, because the model and its runtime are large. Once per computer:
npx @appsoftwareltd/etherpk-mcp semantic setup
That downloads about 300 MB of runtime and a 23 MB model into the cache directory, checking each file against a known fingerprint. From then on the Headless Client keeps a store of your graph's meaning up to date, with no restart: one already running notices within half a minute. The first pass works through every passage in the background, a few minutes for a few thousand pages, on a quarter of the computer's cores so it stays usable meanwhile. After that only what changes is processed, a few seconds after it syncs. A search made while the first pass is still running answers from what has been done so far and tells the agent it is incomplete.
npx @appsoftwareltd/etherpk-mcp semantic status shows each cached graph's progress. The agent
then has two ways to search and is told which to use for what: by words for names, identifiers
and exact phrases; by meaning for questions and descriptions. --no-semantic on an agent's
serve command keeps that agent text-only; semantic remove deletes the runtime and model.
- The store is built and kept current only while a Headless Client is running, which is only
while an agent session has it open. To keep a graph current without an agent, run
npx @appsoftwareltd/etherpk-mcp serve --graph <graph id> </dev/null &yourself. - Each computer does its own work: the numbers are made from your notes, so they cannot go through the Sync Server any more than the notes can. EtherPK's own Search in the browser does not yet search by meaning (Planned Features).
- Protected documents stay out of it entirely.
Publish from an agent
An agent can mark pages public, create or adjust a publication, run a publish and act on the report, fixing the missing links it lists and publishing again (Publishing Your Notes As A Website). Two things stay with you, on purpose:
-
Where the site goes. A publish rewrites the files it owns in its folder and removes strays, so the agent is never allowed to pick the folder. You set it once, on the agent's computer, with the same command a scheduled job would use:
npx @appsoftwareltd/etherpk-mcp publish --sync-server <url> --graph <id> --publication <id> --out <folder>(
--folder <path>in place of the server and graph for a local graph.) That publishes once and remembers the folder; the agent'spublishtool writes there from then on and refuses until it is set. Putting the files online, agit pushsay, is a separate step. -
Diagrams. A Mermaid diagram on a site is drawn by a browser. On the agent's computer, run
npx @appsoftwareltd/etherpk-mcp diagrams setuponce (about 170 MB); until then a publish with diagrams refuses rather than shipping a site with them turned to text. On NixOS, setETHERPK_CHROMIUMto your system Chromium instead.
For the look of a site, the agent can copy a publication's theme into the graph, edit its
templates and stylesheet, preview the result with screenshots when a browser is set up, and
publish; or fill a theme's head include slot from a page of your graph for a snippet alone
(Theming A Published Site).
Commands
Every command is npx @appsoftwareltd/etherpk-mcp <command>. --help prints the full
reference and --version the version.
| Command | What it does |
|---|---|
login --sync-server <url> [--pat <token>] [--recovery-code] |
Sign this computer in as a device of your account on that server, by device approval or, with --recovery-code, your Recovery Code |
graphs [--sync-server <url>] |
List the synced graphs each signed-in account can reach, by name, id and your role |
serve --graph <id or name> [--sync-server <url>] [--no-semantic] |
Serve one synced graph to the agent |
serve --folder <path> [--no-semantic] |
Serve a local graph folder |
logout [--sync-server <url> | --all] |
Forget that server's token and keys and delete its cached graphs. --all forgets every server and clears the whole cache |
semantic setup / semantic status / semantic remove |
Install, check or remove the search-by-meaning runtime and model |
publish (--graph <id or name> | --folder <path>) --publication <id> [--out <dir>] |
Publish one publication to a folder on this computer and print the report. --out sets the folder and is remembered |
diagrams setup / diagrams status |
Install a Chromium for drawing diagrams when publishing, or say which browser would be used |
For a scripted login, ETHERPK_PAT and ETHERPK_RECOVERY_CODE stand in for the prompts.
ETHERPK_MCP_CACHE_DIR moves the cache; set it in the agent's registration as well as your
shell, because the agent starts the Headless Client with its own environment.
What it keeps on your computer
- Your keys, in
~/.config/etherpk/mcp.json, one entry per Sync Server, readable only by your user: the same trust as a browser you have signed in on. - A cache of each synced graph it serves, under
~/.cache/etherpk/mcp/, so a restart fetches what changed rather than everything. Like a signed-in browser's storage it holds your notes readably, so treat the computer accordingly. It is never the source of truth: on every start the server is asked what moved, edits made elsewhere arrive as they happen, and a newer version discards a cache it no longer understands and rebuilds it. Protected documents are never in it. - For a folder, only its index and, once set up, its store of meanings, under
local/in the same cache directory. Moving or renaming the folder starts the index over.
On Windows both paths sit under your user folder, C:\Users\<you>\.config\etherpk\ and
C:\Users\<you>\.cache\etherpk\. Deleting the cache is safe; the next start rebuilds it.
Stopping it
- Revoke the token at the portal under Access tokens and the Headless Client is cut off the next time it talks to the server.
npx @appsoftwareltd/etherpk-mcp logoutforgets the token and keys cached on that computer and deletes the cache.
Anyone who can read your files on that computer can read this account and the cached notes.
logout removes both, and revoking the token stops the account being reachable from there at
all.