Skip to content

Documentation

Folders and projects

A project is a row on the deployment and a folder on your disk. This is the piece of string between them.

One folder, one project

graph link writes .vipl/link.json in the current directory. From then on every command run inside that folder knows which project it belongs to, so graph status, graph check and graph agent all need no arguments.

json
{
  "api": "https://graphlit.co",
  "project_id": "sketch-odtb84p5",
  "name": "Recipe Box"
}
.vipl/link.json. No token, no key, nothing private, so commit it, and everyone who clones the repository is attached to the same project.

The same binding is also recorded in ~/.vipl/links.json, which is how graph status --all and graph agent --all know what exists on this machine without walking your disk.

What is in `.vipl/`

FileWhat it isCommit it?
link.jsonWhich project this folder is, and on which deploymentYes
graph.jsonThe synced copy of the Software GraphYes. It is the contract CI checks against
tasks.jsonThe build plan, and each task's statusYes
node_file_map.jsonNode → file mapping with a content hash per node. This is what drift comparesYes
health.jsonFindings from the last scan, with a fingerprint per finding so a known one stays knownYes
planned_graph.jsonThe snapshot a delta plan is diffed againstYes
history/Previous graph versions, for undoOptional
runs/Per-run records from builds that happened hereNo. Noise in a diff
agent.lockHeld while a runner is serving this folderNo
The rule of thumb: anything that is the architecture is committed, anything that is this machine's activity is not. A generated .gitignore already has the second group in it.

Several projects on one machine

Link as many folders as you like. graph status --all shows every one and whether a terminal is currently serving it, including a terminal on a different machine.

Two linked folders. The circle is the answer to *which of my projects can actually be built right now?*

graph projects asks the deployment the other half of the question: what this account could open, whether or not a folder is attached.

The id in the left column is exactly the one `graph link --project` takes, and the one in the board's URL.

Commands that take a project also accept the name you see on screen, because that is what people remember: graph status invoice works even though the id is g-0c89dc4c. Give a name that does not match, in a terminal, and you get the list to choose from rather than an error.

Moving or renaming a folder

The binding is keyed by absolute path, so a moved folder is a folder the machine no longer recognises. graph link again in the new location. It is instant, and the old entry stops being offered once it no longer exists.

The folder on the server is not this folder

The deployment keeps its own working copy per project. That is what the board reads when nobody's terminal is connected, and what the scaffold writes into when a project is first stood up. Your checkout is yours; the two are synced through the graph and the plan, not by file copying.

Two consequences worth knowing before they surprise you:

  • *`graph tasks` reads this folder's copy of the plan and makes no network call.* graph status asks the deployment. They can differ, most often when a build ran here but the report did not reach the board. That is a feature of tasks (it works offline, and it is what graph run will actually run) rather than a bug in either.
  • Each organisation resolves inside its own subtree on the server. Two organisations both drawing a project called Shop do not share a directory, because the org is half of the address.

Starting from code instead of a drawing

An existing repository does not need drawing. Import code… on the board scans it (Next.js routes, FastAPI endpoints, Prisma and SQL schemas) and produces the graph from what is actually there, with every node marked as having come from code.

The import screen, offering to scan a repository into a Software Graph.
Brownfield import has no node cap. Scale is handled by the view, not by throwing away half your system.

After an import the sync layer has something to compare against, and Keeping the graph true becomes the interesting chapter.