CLI
CLI commands
All the vinc commands, grouped by what they do. Each group starts with every usage form; vinc <command> --help shows the same in your installed version.
Every command also takes the shared flags below and its own --help. In usage forms, replace <...> with your values, choose one side of |, and omit or fill optional [...] parts. Do not paste those punctuation marks into a shell. Getting started is on CLI.
The account CLI is published in vincs 0.1.0 and reports CLI version 0.9.7. Package and CLI versions are independent. Older desktop installers may have different commands; check vinc --help and vinc <command> --help.
Global flags
| Flag | Default | Meaning |
|---|---|---|
--target local|account | app's mode, else local | Which graph to work on. |
--space personal|<team id> | personal | Which space, on the account graph. |
--format human|json|ndjson | human in a terminal, json in a pipe | Output format. --json is short for --format json. |
--debug | off | Write sanitised method, route and status diagnostics to stderr. |
--version, -V | Print the installed version and exit. |
| Variable | Meaning |
|---|---|
VINC_API_KEY | Key for the account graph (vinc_ro_ or vinc_sk_). |
VINC_TARGET | Default for --target. |
VINC_SPACE | Default for --space. |
VINC_FORMAT | Default for --format. |
VINC_API_URL | API address (default https://mcp.vincs.io). |
Commands that read or write a graph also take --owner <scope>. In a local store it picks whose graph to use; the default local graph is tenant:local. On the account target the key decides whose graph it is, so leave it out.
Reading
Works on both the local and the account graph.
# Which graph and space you are on
vinc whoami
# The writing rules for this graph (GRAPH.md)
vinc conventions [--lang en|ko]
# Topics and how many nodes of each kind they hold
vinc domains
# One node that answers a question, with excerpts and links
vinc brief --query "<question>" [--max-excerpts N] [--mode general|current|historical] [--historical] [--as-of <date>] [--known-at <date>]
# Search text and nodes together
vinc search --query "<text>" [--top-k N] [--cursor C] [--detail summary|full] [--mode general|current|historical] [--historical] [--as-of <date>] [--known-at <date>]
# Episodes, newest first
vinc recall [--query Q] [--tenant T] [--workspace W] [--domain D] [--tags a,b] [--limit N] [--rank recency|preference]
# One node, its direct links, or everything within a few steps
vinc node get <id>
vinc node neighbors <id> [--limit N]
vinc node graph <id> [--depth 1-4] [--review-mirror]
# Directed links of one node, a whole topic, or up to 100 ids, with their evidence
vinc edges <id>|domain:<name> [--type <relation>] [--dir in|out|both] [--limit N]
vinc edges --nodes <id> <id> ... [--type <relation>] [--dir in|out|both] [--limit N]
# The shortest path between two concepts
vinc path <a> <b> [--max-depth N]
# Concepts a node probably should be linked to
vinc ties <id> [--limit N]
# The evidence for a decision on a topic, with what conflicts
vinc decide --topic "<topic>" [--depth N]
# How the graph hangs together
vinc diagnose [--kind K] [--node <id>]
# Possible duplicates, and pairs already marked as different
vinc merge candidates [--limit N]
vinc merge rejections
Use node graph --review-mirror with one exact document mirror node ID (concept:doc.<doc id>). It checks the source hash, chunks and provenance links in a read-only mirror_review, without changing links. Omit the flag for the usual graph response.
edges takes one node, a whole topic written as domain:<name>, or up to 100 exact ids after --nodes; give one or the other, not both. Each link comes back with its direction and evidence. Without --dir you get both directions, up to 500 links unless --limit says otherwise. --type matches the relation name or the subtype you wrote.
Flags for search, brief and recall:
| Flag | Default | Meaning |
|---|---|---|
--top-k N | 5 | search: how many results. |
--limit N | 10 | recall: how many episodes. |
--cursor C | search: continue from a previous page's next_cursor. | |
--detail summary|full | summary | search: summary gives excerpts; full gives the whole passage. |
--mode general|current|historical | general | search, brief: current leaves out evidence that is not yet or no longer valid, keeps undated evidence and reports conflicts; it cannot be combined with --historical or --as-of. historical keeps past evidence reachable. |
--historical | off | search, brief: also include claims that are no longer valid. |
--as-of <date> | search, brief: what was valid during YYYY, YYYY-MM or YYYY-MM-DD. Earlier versions of a text are not brought back. | |
--known-at <date> | search, brief: only what the graph had recorded by that date, judged by when each item was first created. Earlier versions of a text are not brought back. | |
--domain D | recall: only this topic. | |
--tags a,b | recall: tags to favour with --rank preference. | |
--rank recency|preference | recency | recall: newest first, or by your pins and tags. |
recall with --query, --tenant, --workspace or --rank preference works on the local target only. On the account graph, use search to find by relevance.
Writing and deleting
Works on both graphs; on the account graph it needs a write key (vinc_sk_). Without --yes, deleting and merging ask you to type yes in a terminal, and stop with exit code 2 in a script.
# Add or update nodes and links from a JSON file, merged by id
vinc ingest --file fragment.json [--create-only] [--review-claims] [--operation-id <uuid>]
# Delete one node and its links (cannot be undone)
vinc delete <id> [--dry-run | --preview-digest <digest>] [--operation-id <uuid>] [--yes]
# Delete one link and keep both nodes
vinc edge delete --from <id> --to <id> --type <relation> [--dry-run | --preview-digest <digest>] [--operation-id <uuid>] [--yes]
# Merge two concepts into the first (cannot be undone)
vinc merge nodes <keep> <drop> [--dry-run | --preview-digest <digest>] [--operation-id <uuid>] [--yes]
# Mark two concepts as not the same
vinc merge reject <a> <b> [--note "<why>"] [--undo] [--operation-id <uuid>]
# Look up what happened to a write whose answer never arrived (applies nothing)
vinc operation status <uuid>
Look before you delete or merge. --dry-run on delete, edge delete, merge nodes or doc rm shows everything the change would touch and applies nothing, so it does not ask for yes. The preview comes with a preview_digest. Run the same command again without --dry-run and with --preview-digest <digest>: it applies only if what it touches has not changed since, and otherwise refuses with preview_conflict, so preview again. A preview that cannot be shown whole (more than 200 rows, or a target you cannot read) is refused rather than cut short. On the account graph a preview also needs a write key.
Retry safely. Give a write a fresh lowercase UUID with --operation-id. If the answer is lost, run vinc operation status <uuid> in the same space before doing anything else. Sending the identical command again with the same id returns the first result marked replayed instead of applying it twice; the same id with different arguments is a conflict. accepted means the outcome is not known yet, and a receipt that cannot be found does not mean nothing was applied, so read the node or document itself to be sure. Receipts are kept until the owner is purged, up to 5000 per owner.
--create-only refuses the whole write before anything changes if any node id already exists, so a create can never edit something that is there. --review-claims also compares Record and Decision claims that name their entity, predicate, scope and value with the claims you already stored, and reports what differs in advisories. It never retires a claim; see the tools.
Fragment format for ingest --file. Nodes and links are merged by id; properties you send replace the stored ones whole.
{
"nodes": [
{"id": "concept:dark-mode", "type": "concept", "title": "Dark mode",
"domain": "app/design", "one_liner": "A darker colour theme for low light."}
],
"edges": [
{"from": "concept:dark-mode", "to": "concept:design-token", "type": "relates_to",
"evidence": "Dark mode is built from the same tokens."}
]
}
Documents
Works on both graphs. On the account target, doc extract preview and --apply both use POST /v1/documents/{id}/extract and require a write key. Preview uses apply:false; it is not a read-key operation.
# Documents, newest first
vinc doc ls
# A document's full text
vinc doc get --id <doc id>
# Store a document from a file, or from standard input
vinc doc put --file notes.md
cat notes.txt | vinc doc put --title "Design review"
# Edit a document in place, only if nobody changed it since you read it
vinc doc put --id <doc id> --file notes.md [--expected-content-hash <hash>] [--operation-id <uuid>]
# Create, and refuse if the id is already taken
vinc doc put --id <doc id> --file notes.md --create-only
# File it under a topic and say when it was true
vinc doc put --id <doc id> [--topic <path>] [--valid-from <date>] [--valid-until <date>] [--superseded-by <doc id>] < notes.md
# Preview concepts, then apply them (account: both require a write key)
vinc doc extract <doc id>
vinc doc extract <doc id> --apply [--operation-id <uuid>]
# Delete a document (cannot be undone)
vinc doc rm --id <doc id> [--dry-run | --preview-digest <digest>] [--operation-id <uuid>] [--yes]
| Flag | Default | Meaning |
|---|---|---|
--file F | standard input | .md, .txt, .rst or .pdf. The title and origin come from the file name. |
--title T | kept when editing | Leave it out to keep the current title; pass --title '' to clear it. |
--origin O | Where the text came from. For display only. | |
--id ID | new document | Edit this document instead of creating one. |
--topic P | kept when editing | The topic the document is about, as a path such as design/tokens. Without it the topic is guessed from the text. |
--valid-from D | kept when editing | When the content became true: YYYY, YYYY-MM or YYYY-MM-DD. |
--valid-until D | kept when editing | When it stopped being true, the end excluded. The document leaves the default search but stays; an empty value makes it current again. |
--superseded-by ID | kept when editing | The document that replaced this one. |
--expected-content-hash H | The content_hash you read with doc get or got from your last doc put. If the stored hash differs, nothing changes and the answer is write_conflict with the current hash: read again and merge. An empty value means the document must not exist yet. | |
--create-only | off | Refuse with write_conflict if --id already exists. |
--operation-id U | A fresh UUID, for a safe retry and operation status. | |
--data PATH | MEMORY_DATA_DIR or ~/.vinc/db | Local target only: which store file to use. Also on doc get, doc rm and doc ls. |
Calling a tool directly
call accepts full MCP names such as vinc_brief and short names such as brief. call fetch is not a CLI tool. See the tools.
# Call any MCP tool by name with JSON arguments
vinc call brief --args '{"query": "release checklist"}'
vinc call <tool> --args-file request.json
echo '<json>' | vinc call <tool> --args-file -
# Deleting tools need --yes
vinc call vinc_delete --args '{"node_id": "concept:old"}' --yes
# Read an agent role, or check a finished answer against it
vinc role get <role>
vinc role check <role> --output answer.md [--person-only-requests '<json>'] [--self-authored]
git diff | vinc role check agent-dev-core --output - --self-authored
role takes a role slug such as agent-dev-core or the exact concept:agent- id. role check runs the role's checks on the complete answer in a file, or on standard input with -, without calling a model, and gives a verdict: pass, block (do not deliver) or interrupt (a person decides first). It exits with 0 on pass and 1 on block or interrupt, so a script can stop a handoff. --person-only-requests is a JSON array of {action, reason} requests for a person, and --self-authored says the answer is a diff the role wrote, so removed lines are not read as proposals. A pass releases the answer and grants nothing else. More on Agents.
On this device
Store and device operations require --target local when the selected target is account. An effective account target from the flag, environment or app mode stops them with exit code 2. This includes export, backup, share, import, store maintenance, serve, graph-md build, store-backed graph-md check and mcp serve-http. refs check and graph-md check --file GRAPH.md --no-store without --doc read files only.
# Register Vinc with an AI host, or remove it
vinc mcp install --client code|desktop|cursor|codex [--config-path F]
vinc mcp uninstall --client code|desktop|cursor|codex [--config-path F]
# Print a settings snippet for any other MCP host
vinc mcp manual
# Start an MCP transport (runs until stopped)
vinc mcp serve [--base <url>] [--token T] [--owner <scope>] [--no-spawn]
# Set VINC_MCP_TOKEN to a strong secret first
vinc --target local mcp serve-http [--host 127.0.0.1] [--port N] [--auth-token T] [--oauth --issuer <url>]
# Point host settings back at Vinc after the app moved
vinc mcp repair
# Write the local graph out as Markdown or CSV files
vinc --target local export --owner tenant:local --out <dir> --format md|csv [--domain D] [--excel]
# A snapshot of the local graph
vinc --target local backup --out <dir>
# Build or check GRAPH.md
vinc graph-md build [--file GRAPH.md] [--out F] [--doc --owner <scope>] [--lang en|ko] [--data PATH]
vinc graph-md check [--file GRAPH.md] [--doc] [--no-store] [--data PATH]
# Compare [[id]] citations in files with a saved manifest
vinc refs check [--manifest F] [--root DIR]
# Requires the account API key in VINC_API_KEY
vinc refs refresh [--manifest F] [--root DIR]
# Make a pack file from part of the local graph, or bring one in
vinc --target local share --owner tenant:local --out pack.json [--domain D] [--tags a,b] [--seed <id>] [--depth N] [--no-records]
vinc --target local import --owner tenant:local --pack pack.json
graph-md check exits with 0 when GRAPH.md passes, 1 when it needs a fix and 2 when something blocks it.
The local export, share and import commands require --owner; use tenant:local for the default local graph. refs check only compares [[id]] citations in files with a saved manifest; it does not query the graph. The default is <root>/scripts/graph-refs.json. Set an account API key in VINC_API_KEY, then run vinc refs refresh to update it. Refresh always reads the account catalog; it does not refresh from the local store.
mcp install, uninstall, repair and manual configure a host without reading a graph. mcp serve preserves the app-mode/VINC_MCP_MODE bridge policy; its account mode proxies the hosted MCP rather than using the terminal REST target. For mcp serve-http, first set a strong secret in VINC_MCP_TOKEN (or configure OAuth/API-key authentication). An HTTP server with no authentication configured refuses to start. vinc mcp manual prints the local stdio entry. For a remote MCP host, use https://mcp.vincs.io/mcp (Streamable HTTP) and complete the host's sign-in flow. Terminal REST keys and MCP sign-in are separate.
Examples
Put a folder of notes in
for f in notes/*.md; do
vinc doc put --file "$f" --format json | jq -r .doc_id
done
List matching titles from the account graph
vinc --target account search --query "accessibility" --format ndjson \
| jq -r '.doc_title // .title // .id' | sort -u
Check GRAPH.md in CI
vinc graph-md check --file GRAPH.md
case $? in
0) echo "GRAPH.md passes" ;;
1) echo "GRAPH.md needs a fix" ;;
*) echo "GRAPH.md is blocked"; exit 1 ;;
esac
Back up and export every night
day=$(date +%F)
vinc --target local backup --out "$HOME/vinc-backups/$day"
vinc --target local export --owner tenant:local --out "$HOME/vinc-exports/$day" --format md
Review possible duplicates in a team graph
vinc --target account --space <team id> merge candidates --limit 20 --format json \
| jq -r '.candidates[] | "\(.a_id) \(.b_id)"'
Maintenance and older commands
domain-backfill (move topics under a parent), store-rebuild (rebuild the local store), migrate-dim (embedding dimension migration), migrate-lex (lexical index migration), migrate-body-mentions (adds the columns that record where in a text each mention sits; nothing is written without --approve), onboard, activate and plan are for maintenance. learner, graph, pin, tag and touch are older local commands kept for existing scripts, and store-probe is used inside the app at start-up. Read --help before running any of them; most need the app closed.
# Maintenance (needs --target local when the account target is selected)
vinc serve [--host 127.0.0.1] [--port N] [--parent-pid PID] [--token T] [--data PATH] [--packs DIR] [--profile FILE]
vinc store-probe --data PATH
vinc store-rebuild --out <empty dir> --model <embedding model>
vinc migrate-dim [--data PATH]
vinc migrate-lex --data <offline copy> [--batch N]
vinc migrate-body-mentions --data PATH [--approve]
vinc domain-backfill [--owner <scope>] [--rename OLD=NEW ...] [--dry-run]
vinc backup --out <dir> [--data PATH] [--packs DIR] [--profile FILE]
vinc onboard --profile auth.json [--passphrase P] [--force]
vinc activate --owner <scope> [--query Q] [--domain D] [--tenant T] [--workspace W] [--rank recency|preference] [--tags a,b] [--limit N] [--now <time>] [--no-model] [--out DIR]
vinc plan recall|search|decide [--query Q] [--topic T]
# Older local commands kept for existing scripts
vinc learner --owner <scope>
vinc graph --owner <scope> [--domain D]
vinc pin --episode <id> [--owner <scope>] [--off]
vinc tag --episode <id> --tags a,b [--owner <scope>]
vinc touch --episode <id> [--owner <scope>] [--now <time>]