Docs

Install wong, connect your machines, and learn how notes, checks, the plugin, the server, MCP and Obsidian fit together.

How wong fits together

wong has two parts. The server keeps the brain: every note with its history, the tasks webhooks leave on notes, and a token per machine. wong on each machine keeps a copy of the brain in ~/.wong as plain markdown, which Claude Code reads and writes as its memory, and syncs it with the server.

The brain has a folder for what applies everywhere and one per project:

~/.wong
├── me/              preferences that apply in every repo
└── projects/
    ├── acme/        shared by acme-api, acme-web, ...
    └── pager/

The Claude Code plugin brings the right notes into each session and tells the agent what went stale. Other agents reach the same brain over MCP.

Install

Start the server

On any machine your others can reach, with Docker:

docker run -d --name wong --restart unless-stopped -p 8787:8787 -v wong:/data ghcr.io/17tayyy/wong
docker exec wong /wong serve --new-token laptop

The second command prints a token. Make one per machine. The server starts empty; the first machine you connect fills it.

With Docker Compose:

services:
  wong:
    image: ghcr.io/17tayyy/wong:latest
    restart: unless-stopped
    ports: ["8787:8787"]
    volumes: ["wong-data:/data"]
volumes:
  wong-data:

Without Docker, download the binary for your platform from the releases and run wong serve --db /var/lib/wong/wong.db under systemd or any supervisor. It listens on :8787.

Connect each machine

On macOS or Linux:

curl -fsSL https://wong.bytay.dev/install.sh | sh -s -- http://wong.lan:8787

The script downloads wong, checks it against the release’s checksums, puts it on your PATH, asks for the token you made for this machine and runs wong setup, which:

  1. pulls the brain from the server;
  2. imports this machine’s Claude Code memory and pushes it;
  3. points Claude Code at the brain: every repo to its project, every other folder to me/;
  4. installs the wong plugin for Claude Code.

On the first machine your memory goes up to the empty server. On the others the brain comes down and their own memory is added. From then on, the plugin pulls when a session starts and pushes when it ends.

On Windows, download wong-windows-amd64.exe from the releases, save it as wong.exe in a folder on your PATH, and run wong setup http://wong.lan:8787. With Go 1.27 or later, go install github.com/17tayyy/wong/cmd/wong@latest works anywhere.

Without a server

To try wong on one machine, run the script without a url:

curl -fsSL https://wong.bytay.dev/install.sh | sh

wong setup <url> connects that machine to a server later.

How memory is grouped into projects

Repos that share a parent folder become one project: ~/acme/acme-api and ~/acme/acme-web both go to acme. A folder of unrelated repos, such as ~/code or ~/projects, is the exception, and each repo in it is its own project.

wong import --dry-run shows the grouping before anything is written, and --map PATH=ID changes it, on wong import or wong setup. Nothing in ~/.claude is changed, and wong link --remove points a repo back at Claude Code’s own memory.

Notes

The format

A note is Claude Code’s memory format plus a few fields at the top level of its frontmatter:

---
name: move-billing-to-stripe
description: Decided 2026-09-02 to move billing to Stripe; tracked in ENG-15
kind: decision
scope: project:acme
tags: [billing, payments]
sources:
  - linear:ENG-15
  - file:acme-api/app/billing/webhooks.py
verified: 2026-10-27
---

Billing moves to Stripe. Webhooks first, see [[billing-webhooks]].
Field Meaning
kind preference, project, person, client, decision or reference.
scope global for notes in me/, or project:<id>.
tags A few tags. wong refuses a new spelling of a tag already in use.
sources What the claims rely on: linear:<ID>, file:<repo>/<path>, commit:<repo>@<sha>, note:<name> or a URL.
verified When the note was last checked against its sources. Set it with wong note verify, never by hand.
pending release or main when the note leaves work for the next v* tag or push to the main branch.

Notes point to their sources instead of copying their state: “tracked in ENG-15”, not “ENG-15 is in progress”. Link related notes with [[name]].

Working with notes

Agents use these, and so can you:

wong note search billing stripe     # by topic, accents and case ignored
wong note show move-billing-to-stripe
wong note write --to acme --name stripe-retries --kind reference \
  --description "Stripe retries failed webhooks for three days" \
  --source linear:ENG-15 --tag billing < body.md
wong note verify stripe-retries --source file:acme-api/app/billing/webhooks.py
wong note move stripe-retries --to me

wong note write refuses a tag that is a new spelling of one in use, a link to a note that does not exist, and a note that seems to repeat another, and lists the related notes the new one does not link yet. wong tidy lists duplicate preferences, notes in the wrong folder and notes that grow by dated additions.

Checking

What wong check finds

wong check compares every note with what it cites, from the date it was last written or verified:

  • Stale: the note contradicts its source. A file it cites was deleted, an issue it calls open was closed, a note it links to does not exist, or a deploy it leaves work for went out.
  • Review: the note may be outdated. A file or commit cannot be found, a commit is on no remote branch, an issue closed after the note was written, a tag is a spelling of another, or its dates are later than the file’s own.

Files and commits are looked up in the project’s repos. Linear issues are checked when LINEAR_API_KEY holds a personal API key.

Tasks from webhooks

With webhooks set up, the server does not wait for a session to notice. A push that removes a file a note cites, an issue that closes, or a release a note waits for leaves a task on that note. wong tasks lists them, the session start names them, and each closes by itself once the fixed note reaches the server.

Work left for a deploy

A note with pending: release waits for the next v* tag of its project’s repos; pending: main waits for the next push to the main branch. When it happens, whoever pushed it, the next session in that project says so before anything else, and the agent tells you what is left.

The Claude Code plugin

The plugin answers four of Claude Code’s hooks:

  • Session start: pulls the brain, then adds the index of me/, the tags in use, the format for new notes, any work left for a deploy, and the notes of the project that may be outdated.
  • Before reading or editing a file: the notes that cite that file or its folder, once per session.
  • After saving a note: what the note lacks, for the agent to fix in one edit.
  • Session end: records the skills in use, commits the brain’s changes and pushes them to the server.

It also ships the maintain-brain skill, which tells the agent how to fix each kind of finding and how to write notes that point at their sources. Agents fix stale notes after the task you asked for, and up to three notes to review per session.

The server

Tokens

Each machine has its own token, and every change is signed with it. wong serve --tokens lists them with their last use, and --revoke-token <name> revokes a lost machine’s. With Docker, run them as docker exec wong /wong serve --tokens.

Sync and conflicts

wong pull, wong push and wong sync move changes between the brain and the server. A note changed on two machines at once is never overwritten: the server’s version goes to ~/.wong/.wong/conflicts, and wong resolve <path> --keep local|server settles it.

Reaching it from outside

To use the server from outside your network, put it behind a tunnel or a proxy with a certificate, or pass --tls-cert and --tls-key. wong only sends a token over plain http to an address on your own network.

Dashboard

Open the server’s address in a browser and sign in with a token, such as one made with --new-token browser. Read and edit notes in place, rename, move or delete them, undo any change, see what each machine changed, and browse the brain as a graph.

Webhooks

  • GitHub: point a webhook for push events at /hooks/github, with the secret in WONG_GITHUB_SECRET on the server.
  • Linear: point a webhook for issue events at /hooks/linear, with the secret in WONG_LINEAR_SECRET.

With Docker, pass the secrets with -e. Only /hooks/* needs to be reachable from the internet. The plugin records which GitHub repo belongs to which project.

MCP

The server speaks MCP over Streamable HTTP at /mcp, with the tools get_context, search_notes, read_note, write_note, edit_note, verify_note, move_note and delete_note. They follow the same rules as the plugin’s skill, and every change is signed with the token that made it.

For agents that start MCP servers as a command, wong mcp relays over stdio with this machine’s token:

codex mcp add wong -- wong mcp

Clients that speak HTTP can use <server>/mcp directly with a token of their own.

Obsidian

~/.wong opens as an Obsidian vault: links resolve the same way for Obsidian and for agents, and Obsidian’s settings stay on each machine.

wong obsidian export ~/vaults/brain
wong obsidian import ~/vaults/notes --to acme --dry-run

The import keeps each note’s properties, takes tags from properties and #tags, never writes over a note the brain has, and lists attachments and links that reach no note.

Commands

Command What it does
wong setup [url] Make the brain this machine’s memory, with a server or on its own
wong import Bring Claude Code’s memory folders into the brain
wong link Point Claude Code’s memory at the brain, or back with --remove
wong check Check every note against what it cites
wong note … show, search, write, verify, move, remove
wong tags List the tags in use
wong tidy Duplicate preferences, misplaced notes, notes that grow by additions
wong skills save Record where your skills come from
wong serve Run the server
wong remote, pull, push, sync, resolve Sync with the server
wong tasks List the tasks webhooks left
wong mcp Serve the brain over MCP on stdio
wong obsidian export/import Move notes between the brain and a vault

Every command explains itself with --help.