Link is a tool to track relationships between entities in an agent-friendly way. Build and query knowledge graphs through a simple API, WebSocket interface, or MCP.
- Model people, projects, documents, systems, or any other domain with custom node and edge types.
- Capture both directional and mutual relationships so the graph matches how your data actually connects.
- Keep structured metadata on records without blocking extra fields that matter to your workflow.
- Query and update the same graph from the web app, HTTP API, WebSocket clients, or MCP-compatible agents.
- Start quickly with built-in starter types for an empty graph, or define your own model from scratch.
- Store graph data as plain JSON files that are easy to inspect, diff, review, and version with Git.
- Validate the graph before committing to catch malformed records, broken references, and merge issues early.
Install the latest Linux or macOS binary release:
curl -fsSL https://raw.githubusercontent.com/pablozaiden/installer/main/install.sh | sh -s -- pablozaiden/linkThe installer downloads the latest release for your platform and installs it as link-cli in $HOME/.local/bin. If that directory is not on your PATH, the installer prints the shell profile line to add.
Installed binaries can check for or install release updates:
link-cli update --check
link-cli update
link-cli update --version 0.1.0The update command works from an installed link-cli binary. When running from source, use the installer or download a release binary instead.
bun install
bun run devOpen the app at the printed server URL, usually http://localhost:3000.
To create the default node and edge types for an empty graph, run:
bun src/index.ts seedCommon checks:
bun src/index.ts validate
bun test
bun run buildRunning link-cli with no arguments shows the current CLI version and available top-level commands:
link-cli
link-cli web
link-cli validate
link-cli seed
link-cli update --check
link-cli graphwebstarts the web UI, HTTP API, realtime endpoint, and MCP endpoint.validatevalidates graph JSON files.seedcreates the default graph node and edge types when the graph is empty.updatechecks for or installs newer release binaries.graphexposes the same graph actions as the MCP server for direct CLI use.
Graph CLI action names match MCP tool names exactly. Use link-cli graph to list actions and link-cli graph <action> --help for action-specific help:
link-cli graph get_graph
link-cli graph search_graph --query ada
link-cli graph create_node --json '{"name":"Ada Lovelace","typeId":"person"}'The default graph path is ./.data/graph, but Link does not create .data or graph collection directories until a mutation saves data or explicit seed bootstrap data is written:
.data/
graph/
node-types/
person.json
project.json
edge-types/
works-on.json
related-to.json
nodes/
ada-lovelace.json
edges/
ada-lovelace-works-on-link.json
If the graph is empty and you want the built-in starter types, run bun src/index.ts seed or link-cli seed. Seeding is skipped when any graph JSON records already exist, so it will not backfill defaults into an existing graph.
- Create a new, emtpy Git repository.
- Run Link locally and edit through the UI, HTTP API, MCP tools, or CLI graph actions. Use
link-cli seedfirst only when you want default types in an empty graph. - Inspect JSON changes under
.data/graph. git add .data/graph && git commit.git pulland merge or resolve JSON conflicts.- Run
link-cli validateto ensure the graph is consistent. git push.
| Variable | Default | Description |
|---|---|---|
PORT / LINK_PORT |
3000 |
HTTP server port. LINK_PORT wins when both are set. |
LINK_DATA_DIR |
./.data |
Base data directory. Graph JSON is always stored under the fixed graph/ subdirectory inside it. |
LINK_GRAPH_WATCH_DEBOUNCE_MS |
50 |
Debounce for filesystem graph change events in web mode. Set to 0 to disable watching for external graph JSON changes. |
Core endpoints:
GET /api/healthGET /api/graphGET /api/node-typesPOST /api/node-typesPUT /api/node-types/:idDELETE /api/node-types/:idGET /api/edge-typesPOST /api/edge-typesPUT /api/edge-types/:idDELETE /api/edge-types/:idGET /api/nodesPOST /api/nodesGET /api/nodes/:idPUT /api/nodes/:idDELETE /api/nodes/:idGET /api/edgesPOST /api/edgesGET /api/edges/:idPUT /api/edges/:idDELETE /api/edges/:idGET /api/search?q=...GET /api/nodes/:id/context
Example:
curl -s -X POST http://localhost:3000/api/nodes \
-H 'content-type: application/json' \
-d '{"name":"Ada Lovelace","typeId":"person"}'This example assumes the person node type already exists, either from link-cli seed or from creating that type yourself.
Connect a WebSocket client to /api/realtime. Successful in-process graph mutations broadcast graph.changed events. The web server also watches graph JSON files and broadcasts graph.changed when another process, such as link-cli graph, changes the graph. Clients should refetch /api/graph after receiving a change event.
The /mcp endpoint is a standard MCP Streamable HTTP transport powered by @modelcontextprotocol/sdk. MCP clients connect to:
http://localhost:3000/mcp
The server exposes local graph tools through MCP tools/list and tools/call, including get_graph, search_graph, get_node_context, and type/node/edge mutation tools. The same tool names are available through link-cli graph <tool_name> when MCP is not connected.
Agent workflow guidance is packaged as the Agent Skills-compatible skill in skills/link/SKILL.md.
Build the image:
docker build -t link .Run with graph data mounted:
docker run --rm -p 3000:3000 -v "$PWD/.data:/data" linkUse LINK_DATA_DIR if you mount the data directory somewhere else inside the container. To seed an empty mounted graph, override the container command explicitly:
docker run --rm -v "$PWD/.data:/data" link link-cli seed