This is the full, technical list of every command. If you're just starting, you only
need a handful (create-vivary init, doctor, tropo check); the getting started
guide walks through those. Come back here for the details.
Every CLI across the four layers. All engines are zero-dependency Python (3.11+);
the CLI command names are tropo / ozone / exo / create-vivary regardless of
how you install them.
- Install (PyPI):
pip install vivary - Run without installing (uv):
uvx vivary-tropo check,uvx vivary-ozone review, … - Scaffold (npm):
npm create @vivary@latest my-workspace/npx @vivary/create@latest my-workspace - From a repo checkout:
python packages/tropo/tropo.py check, etc.
Features called out as unreleased are present on the dev branch and generated
site docs, but are not available from the current PyPI/npm packages until the next
release-train PR bumps and publishes them.
Exit codes are uniform: 0 success · 1 findings/errors · 2 usage/config
error. Gate CI on the exit code; don't parse text. Every command takes --json for
machine-readable output.
Every core CLI also accepts --receipt PATH, or the equivalent
VIVARY_RECEIPT_LOG=PATH, to append one local JSONL run receipt after the command
finishes. This is not telemetry: Vivary does not send receipts anywhere, does not
start a background process, and does not record stdout, stderr, environment variables,
file contents, raw query text, target ids, or local paths. Receipts record only a small
debug envelope: schema version, tool/version, command, flag names, argument count,
exit code, duration, Python version, and platform. Receipt targets must be regular
files; symlink targets, symlink/junction directory ancestors, directory targets, and
Windows device names are refused.
Install the vivary meta package when you want a human-readable pull surface over
those receipts:
tropo check --root . --receipt .vivary/receipts.jsonl
vivary logs .vivary/receipts.jsonl
vivary logs .vivary/receipts.jsonl --failed --tail 10 --json
vivary logs email .vivary/receipts.jsonl --to support@example.com --out .vivary/support.emlvivary logs email writes a local .eml draft or prints a mailto: URL. It does not
connect to SMTP, call an API, upload logs, or send mail by itself.
The CLI is the agent API. Every command an agent needs to run Vivary is here — no
MCP server, no special protocol. Commands that interact or install also accept --yes
(auto-confirm all prompts), --auto (agent selects from explicit storage/privacy/size
hints), and --dry-run (inspect without side effects). See
SPEC-data-layer.md for the full agent CLI contract and the new
storage/migration commands.
vivary logs [PATH] [--json] [--tail N] [--failed]
vivary logs email [PATH] --to EMAIL [--subject TEXT] [--out FILE]
[--json] [--tail N] [--failed]
The vivary meta package installs the four core CLIs and adds a tiny local helper for
the receipt files they emit. vivary logs summarizes a JSONL receipt file as text or
JSON. vivary logs email creates a redacted support email draft from the same
whitelisted receipt fields. Unknown fields, malformed lines, stdout/stderr-like fields,
file contents, raw query text, target ids, and local paths are not copied into the
summary.
| Command | Job |
|---|---|
logs [PATH] |
Read local JSONL receipts from PATH, VIVARY_RECEIPT_LOG, or .vivary/receipts.jsonl and print a summary. |
logs --failed --tail 10 |
Show only recent failed receipts. |
logs --json |
Return {summary, records} for agents and bug-report tooling. |
logs email ... --out FILE |
Write a local .eml draft; directory targets, symlink targets, symlink/junction ancestors, and Windows device names are refused. |
logs email ... |
Without --out, print a mailto: URL for the user's mail client. |
tropo [command] [paths...] [--lenient | --strict] [--json] [--quiet]
[--depth N] [--max-entries N] [--out FILE] [--packs a,b]
[--root DIR] [--config PATH] [--receipt PATH]
[--type TYPE] [--path GLOB] [--edge FIELD[:TARGET]]
[--snippet N] [--explain] [--mode text|vector|semantic] [--budget N]
A document's type is the folder it lives in (decisions/0001.md → type
decision). Metadata is only what can't be derived from where a file sits and what it
says. tropo.toml declares the types.
| Command | What it does |
|---|---|
check [paths] |
Validate frontmatter + the graph. Opinionated: warnings fail by default. Default command. |
signal [paths] |
Print only the irreducible metadata per doc — the literal signal, noise stripped. |
types |
Print the resolved, merged type registry. |
stats |
Document counts per type + a health summary. |
graph [--json] |
Emit the typed graph: nodes (id,type,path) + edges (from,field,to,broken). |
blast <id> [--depth N] |
The blast radius of <id>: everything that (transitively) refs it — what a change could touch. |
view [graph | blast <id>] [--out FILE] |
Render the graph (or one radius) as a single self-contained HTML file. --out must stay inside the tropo root, refuse symlink targets, and rewrite the workspace output path without mutating hard-linked files outside the workspace. |
plan <change.toml> |
Simulate a change (remove/retype/break/add) and show the graph delta. |
fix [--dry-run] |
Strip redundant frontmatter (W210 — a field equal to its derived value). The only mechanical edit tropo makes. |
init [DIR] [--packs a,b] |
Scaffold a tropo.toml (optionally composing reusable type packs). |
find <text> [--budget N] [--k N] [--json] |
Human-friendly context packet: the smallest typed nodes/files worth opening first, with reasons and snippets trimmed to an approximate token budget. |
query <text> [--k N] [--mode text|vector|semantic] [--type TYPE] [--path GLOB] [--edge FIELD[:TARGET]] [--snippet N] [--explain] [--json] |
Filtered graph search over typed nodes. Default text searches id/title, frontmatter, path, body, and outbound edge context. vector uses dependency-free local typed vectors when .vivary/storage.toml enables them, prefers stored embedded vectors when current rows exist, and otherwise falls back to text search. semantic calls an explicitly configured optional semantic-memory provider and returns typed node ids. |
migrate --from file --to embedded [--dry-run] [--json] |
Move file-backed graph data into the configured embedded backend. When local vector policy is explicitly enabled, migrated rows also include typed-node vectors and provenance metadata. Cloud migration, non-file sources, backend installation, and migrated_at tracking are future 0.3.x work. |
map [--root PATH] [--depth N] [--max-entries N] [--json] |
Read-only filesystem inventory of a repo/vault/docs tree — no tropo.toml required. See Filesystem map below. |
tropo find is the default "what should I read first?" command for humans and agents.
tropo query is the lower-level filtered search primitive. By default both are
graph/text retrieval, not the CocoIndex active-context sidecar. On the unreleased
dev branch, tropo query --mode vector is a dependency-free typed-vector mode:
it preserves type/path/edge filters and returns typed Vivary node ids without
installing an embedding provider. Enable it explicitly in .vivary/storage.toml:
[storage.embedding]
enabled = true
provider = "local-hash"
dimensions = 128When the workspace is configured for embedded storage and current migrated vectors
exist, JSON output reports vector.source: "stored" and vector.index: "embedded".
Stored-vector query validates compact metadata first and asks the backend for a
bounded candidate set. If the embedded index is empty, stale, missing vectors,
dimension mismatched, too large for conservative validation, or unavailable, --mode vector reports status: fallback, fallback: "text", and a detail string, then
returns deterministic typed text results.
Workspaces that enable local vectors without embedded storage still use computed
graph-node vectors and report vector.source: "computed". Without local vector
config, --mode vector falls back to the normal typed text search.
tropo query --mode semantic is an optional-provider bridge: it requires
.vivary/memory.toml to enable a supported semantic-memory provider, and today that
means the separate vivary-memory-cognee package must be installed and indexed by
the user. It does not add Cognee or network calls to vivary-tropo core. Use
create-vivary init ... --active-context cocoindex-code when a coding workspace
needs semantic code candidates.
tropo migrate --from file --to embedded --json reports an embedding object.
Without [storage.embedding], the status is disabled and rows stay plain typed
nodes. With enabled = true and provider = "local-hash", each migrated row gets a
vector plus embedding_provider, embedding_dimensions, embedding_version,
embedding_scope, embedding_text_fingerprint, and source_fingerprint. Bad
embedding config fails before backend writes. Root and nested exclude rules,
symlink/junction pruning, and out-of-root path checks run before any text is
embedded. Embedded storage paths must stay inside the workspace and avoid symlink or
junction-backed directories. Real file-to-embedded migration replaces the embedded
node snapshot, so deleted, renamed, or newly excluded nodes do not leave stale
embedded rows.
Simple rule: start with plain tropo find or tropo query. Reach for the other
modes only when the plain graph search is not enough.
| Mode | Use it when | What changes |
|---|---|---|
text (default) |
You want deterministic local search over the typed graph. | No setup, no index, no provider, no network. |
vector |
You want local "close wording" ranking over graph nodes, but still no provider. | Requires explicit [storage.embedding] provider = "local-hash"; embedded workspaces use stored vectors when current, otherwise deterministic text fallback. |
semantic |
You already chose and indexed an optional semantic-memory provider. | Calls that provider, then filters hits back to known typed Vivary node ids. |
Useful retrieval flags:
| Flag | Effect |
|---|---|
--type TYPE |
Restrict to a document type; repeat for multiple allowed types. |
--path GLOB |
Restrict to path globs such as decisions/*; repeatable and slash-normalized for Windows paths. |
--edge FIELD[:TARGET] |
Require an outbound graph edge field, optionally pointing at a target id. |
--snippet N |
Include up to N snippet characters per result; 0 disables snippets. |
--explain |
Include stable match reasons such as title/id, frontmatter, path, body, or edge context. |
--mode text|vector|semantic |
query only: use dependency-free graph/text search, dependency-free local typed-vector search, or call the configured optional semantic-memory provider. |
--budget N |
find only: approximate token budget for the returned context packet. |
tropo find "where is release truth owned" --root . --budget 800 --json
tropo query "release truth" --type decision --path "decisions/*" --explain --json
tropo query "agent workspace" --edge affects:agent-workspace
# Unreleased dev branch until the next package publish:
tropo query "release truth" --mode vector --json
tropo query "release truth" --mode semantic --jsoncheck is strict by default — untyped docs, unknown fields, broken refs, and
redundant frontmatter all fail it. Relax when you need to:
tropo check # strict: any warning fails (exit 1)
tropo check --lenient # warnings shown, exit 0
tropo check --quiet # hide warnings, errors onlyOr persistently per vault, in tropo.toml: [base] strict = false. --strict forces
it back on (overrides a lenient config). strict is tighten-only across nested
configs — a sub-folder may turn it on, never off.
| Code | Level | Meaning |
|---|---|---|
E000 |
error | file can't be read |
E001 |
error | frontmatter isn't valid YAML / not a mapping |
E101 |
error | required field missing for the type |
E102 |
error | required field is empty |
E103 |
error | field value violates its type spec |
W201 |
warn | untyped document (no ancestor folder is a registered type) |
W202 |
warn | unknown field for the type (typo? add it to the schema) |
W210 |
warn | field equals its derived value (noise — run tropo fix) |
W220 |
warn | ref points at no document id (broken edge) |
(Under the default strict mode, every W2xx fails the check.)
tropo map [PATH | --root PATH] [--depth N] [--max-entries N] [--json]
Read-only inventory of a large repo, vault, docs tree, or file system — no
tropo.toml required, and nothing is ever written. Meant to let an agent
understand the shape of a tree without opening hundreds of files: a directory
table, extension and size summary, existing index/routing files, and folders
that look like modules but have no index.md/README.md.
| Flag | Effect |
|---|---|
PATH / --root PATH |
Tree to inventory (default: current directory) — give one or the other, not both; extra positional paths are an error. Does not need a tropo.toml. |
--depth N |
Directory-table depth, root = depth 0 (default: 3). Counts (totals, extensions, largest files, missing-index detection) always cover the whole tree regardless of --depth — only the table rows are limited. |
--max-entries N |
Cap the number of directory rows — the markdown table and the JSON directories array alike (default: unlimited). Summary sections are never capped. |
--json |
Emit a single JSON object with sorted keys and deterministic ordering (stable to diff and safe to cite). |
The output is safe to share: the root field (and the markdown heading) is the
mapped directory's basename only — the absolute local path never appears.
Every other path is root-relative with forward slashes.
Skipped: .git, node_modules, __pycache__, .venv, venv, dist,
build, .astro, .next, target, plus any exclude patterns from a
tropo.toml found by walking up from the map root (the same is_excluded
mechanism check/graph use, applied to directories and individual
files) — a missing or invalid config never blocks the map. When the map root
sits below the config root, path-anchored excludes are rebased onto the map
root, so exclude = ["docs/private"] still hides private/ when you run
tropo map docs. Directory junctions and symlink cycles are pruned by real
path, so a looping tree never inflates counts. "Likely modules without an
index" = directories at depth 1-2 with 5 or more files (recursive count) and
no index.md/README.md.
$ tropo map --root . --depth 2
# tropo map: repo
163 file(s), 65 director(y/ies), depth ≤ 2
## Directories
| Path | Depth | Files | Size | Dominant extensions | Index? |
|---|---|---|---|---|---|
| . | 0 | 163 | 1.6MB | .md (89), .py (14) | yes |
| docs | 1 | 22 | 574.0KB | .md (18), .webp (4) | yes |
| packages/tropo | 2 | 6 | 128.4KB | .py (2), .md (2) | no |
## File extensions (top 10)
...
## Likely modules without an index
Directories at depth 1-2 with >= 5 files (recursive) and no `index.md`/`README.md`:
- packages/tropo
[base]
derive = ["id", "title", "created", "updated"] # never required, never noise
optional = { tags = "string-list", status = "string" } # any doc MAY carry these
allow_untyped = true # W201 instead of error for files outside any type root
strict = true # warnings fail check (the opinionated default)
timezone = "local"
packs = ["dev-project"] # compose reusable type bundles
[types.decision] # table key = the TYPE name
folder = "decisions" # the directory basename that roots it
required = { status = "enum:proposed|accepted|superseded", date = "date" }
optional = { supersedes = "ref", related_modules = "ref-list" }Field specs: string, slug, date, datetime, url, string-list, any,
enum:a|b|c, and the graph types ref / ref-list (these become edges).
Built-in packs: dev-project, repo-graph, and coordination. Local
.tropo/packs/<name>.toml files take precedence over bundled packs. Use
coordination when exo should be allowed to write assignee:
packs = ["repo-graph", "coordination"]ozone [review | impact <id> | packs] [--root DIR] [--json] [--strict]
[--pack structure|context-budget|editorial|all] [--receipt PATH]
Where tropo check asks "is each document valid?", ozone reviews the whole graph
and a change's impact. It reads tropo's graph in-process (one graph, no fork).
| Command | What it does |
|---|---|
review |
Run a deterministic review pack. Defaults to --pack structure for stable CI; use --pack context-budget for context bloat, --pack editorial for writing workspaces, or --pack all for every pack. Advisory by default (exit 0); --strict makes it a gate (exit 1 on warnings). |
impact <id> |
The blast radius of a node — what (transitively) depends on it, with distance + the edge field it came in by. |
packs |
List the available rule packs. |
| Rule | Severity | Fires when |
|---|---|---|
change-unverified |
warn | a changes/ node has no verification edge |
change-ungated |
info | a changes/ node has no gates edge |
module-unverified |
info | a modules/ node has no verification edge |
orphan |
info | a node has no edges in or out |
broken-edge |
warn | an edge points at a missing node (tropo check enforces this) |
context-budget reviews only public routing/startup surfaces:
AGENTS.md, CLAUDE.md, STRATO.md, STATE.md, SOUL.md, README.md,
modules/index.md, and modules/*/index.md. It does not read private memory files
such as USER.md, MEMORY.md, memory/**, heartbeat reports, .vivary/**, or
.git/**.
| Rule | Severity | Fires when |
|---|---|---|
module-index-missing |
warn | a modules/<name>/ directory has no index.md |
legacy-module-file |
warn | modules/<name>.md coexists with modules/<name>/index.md |
always-on-large |
info | a root routing contract exceeds its fixed line/char threshold |
module-index-large |
info | modules/index.md or modules/*/index.md exceeds 120 lines or 8000 chars |
bulk-load-cue |
info | public routing text tells agents to read/load/scan/open whole repos, docs trees, folders, or everything |
duplicate-routing-block |
info | an exact normalized routing block over 100 chars repeats across public routing surfaces |
editorial reviews writing workspaces using graph edges only. It stays silent for
non-writing workspaces, and looks for coverage across drafts/, manuscripts/,
reviews/, editorial-reviews/, edits/, revisions/, outlines/,
structures/, and beats/.
| Rule | Severity | Fires when |
|---|---|---|
draft-unreviewed |
warn | a drafts/ or manuscripts/ node has no linked review |
draft-unedited |
info | a draft/manuscript has no linked edit or revision |
draft-structure-missing |
info | a draft/manuscript has no linked outline, beat sheet, or structure note |
review-unlinked |
warn | a review is not linked to a draft or manuscript |
edit-unlinked |
warn | an edit/revision is not linked to a draft, manuscript, or review |
ozone review --root . # advisory report
ozone review --root . --strict # gate: exit 1 if any warning (CI / pre-merge)
ozone review --root . --pack context-budget
ozone review --root . --pack editorial
ozone review --root . --pack all --json
ozone impact human-gates --root . --jsonexo [conflicts | board | claim <id> --agent <handle> | roles] [--root DIR] [--json]
[--receipt PATH]
The outermost, thinnest layer — engaged only when one agent becomes many. Graph-native
and deterministic; it doesn't run agents, it coordinates them. claim is the only
writer, and it refuses to write unless the workspace declares assignee through
packs = ["coordination"].
| Command | What it does |
|---|---|
conflicts |
Among active work items (changes with status: active), flags pairs that share an outbound target — two in-flight changes touching the same node. |
board |
Work items grouped by status (and @assignee if the workspace declares one). |
claim <id> --agent <handle> |
Claim a work item under changes/ by setting top-level assignee; optional leading @ is accepted and stripped before storage. Refuses symlinked or out-of-workspace work item files and replaces the workspace file instead of truncating hard-linked targets. |
roles |
The bounded worker contracts: Orchestrator · Scout · Researcher · Builder · Verifier · Reviewer · Archivist. |
exo conflicts --root . # who would collide
exo board --root . # what's in flight
exo claim local-ci-baseline --agent connie --root .
exo roles # the role grammarJSON output for claim includes id, path, assignee, previous_assignee, and
changed.
create-vivary init <target> [--preset coding|second-brain|knowledge-work|writing] [--force] [--obsidian]
[--active-context cocoindex-code]
[--storage auto|file|embedded|cloud] [--provider lancedb|sqlite-vec|qdrant|astra]
[--memory none|local|cognee]
[--auto] [--yes] [--dry-run] [--json]
[--size small|medium|large] [--privacy local|cloud] [--receipt PATH]
create-vivary wizard <target> [--storage auto|file|embedded|cloud] [--provider lancedb|sqlite-vec|qdrant|astra]
[--memory none|local|cognee] [--yes] [--dry-run] [--json] [--receipt PATH]
create-vivary capabilities [--preset coding|second-brain|knowledge-work|writing] [--json]
[--receipt PATH]
create-vivary doctor <target> [--json] [--trend] [--receipt PATH]
create-vivary adopt <target> [--preset coding|second-brain|knowledge-work|writing] [--yes] [--json]
[--receipt PATH]
| Command | What it does |
|---|---|
init <target> |
Lay down a complete workspace: the agent contract, the strato shell (SOUL/USER/STATE/MEMORY), runtime skills, a tropo.toml, a starter typed graph, and optional storage or semantic-memory config based on flags/wizard answers. |
wizard <target> |
Re-run the setup wizard on an existing workspace to reconfigure storage and optional semantic-memory policy. |
capabilities |
List optional capabilities for a preset: storage, semantic memory, and preset-specific sidecars. |
doctor <target> |
Validate a workspace: required files, active privacy ignore rules, module directory indexes, tropo graph health, backend reachability, and semantic-memory status. |
adopt <target> |
Bring Vivary to an existing repo or vault. Only adds files that don't already exist; never moves, renames, edits, or overwrites anything. Dry-run by default. |
| Flag | Effect |
|---|---|
--preset coding|second-brain|knowledge-work|writing |
Which starter graph to seed (default coding). |
--force |
Overwrite existing scaffold files and remove stale generated files, but still refuses symlinked destination parents or paths that resolve outside the target workspace. |
--obsidian |
Also drop an opt-in Obsidian vault config (graph coloured by type). |
--active-context cocoindex-code |
For coding workspaces, add CocoIndex-code sidecar profile (skill, docs, graph nodes, gitignore). Does not auto-install or enable MCP. |
--storage auto|file|embedded|cloud |
Storage backend to configure. auto = LanceDB locally. Default: file (no new deps). Cloud writes config only; the tropo cloud backend is future 0.3.x work. |
--provider lancedb|sqlite-vec|qdrant|astra |
Which implementation to use for the selected tier. lancedb is the shipped embedded provider. |
--memory none|local|cognee |
Optional semantic-memory policy. Default: none. local writes local-only policy. cognee writes gated Cognee policy and graph docs, but does not install Cognee or index content. |
--auto |
Agent mode. Skip all interactive prompts; pick the best option from explicit --storage, --privacy, and --size hints. |
--yes |
Auto-confirm installs and confirmations. Safe to combine with --auto for fully non-interactive agent use. |
--dry-run |
Print what would be scaffolded and installed; do not write, install, or clean stale files. |
--json |
Machine-readable output. Reports ok, root, preset, storage, provider, memory, capability metadata, installed, files, config paths, and dry_run. |
--size small|medium|large |
Hint for --auto storage decisions. Agents can pass this after inspecting the repo. |
--privacy local|cloud |
Hint for --auto storage decisions. |
doctor checks that USER.md, MEMORY.md, memory/*, and heartbeat-reports/*
are actively ignored. Comments, negations, and unrelated patterns that merely contain
those names do not count. If .vivary/memory.toml exists, doctor reports semantic
memory as disabled, healthy, configured, unavailable, misconfigured, or
privacy-failed without requiring optional Cognee support to be installed.
doctor --trend is opt-in and is the only thing that writes .vivary/doctor-state.json
(plain doctor stays read-only). It compares this run's graph health, module-index
count, and file count under modules/ against the prior recorded run and reports
signed deltas — a short "trend vs <date>" section in human mode, or a trend object
(prior/current/deltas) in --json mode. The first --trend run on a workspace
has no prior state, so it reports "first recorded run" and just writes the baseline. A
corrupt or unreadable state file is treated the same way — a warning, not a failure —
and gets overwritten with a fresh one.
When --storage embedded (or auto) is selected and vivary-tropo[embedded] is not yet installed, init installs it via pip before continuing unless --dry-run is set. In --json mode, "installed": ["lancedb"] reports what was added. Without --yes, a single confirmation prompt fires before any pip install. For scripted storage selection, pass --no-wizard --storage embedded --yes or use --auto; in human mode, the wizard asks and its answers drive storage. --auto never selects Cognee by itself.
adopt brings the Vivary scaffold to a repo or vault that already exists, without
disturbing anything already there.
| Flag | Effect |
|---|---|
--preset coding|second-brain|knowledge-work|writing |
Starter graph to seed. Default: auto-detected — coding for a code-file majority, second-brain for a markdown-file majority. --json/text output states the chosen preset and the reason. |
--yes |
Write the planned files. Without it, adopt only analyzes and prints a plan (dry-run is the default, unlike init). |
--json |
Machine-readable output: {mode, root, preset, preset_reason, would_create, kept, followups, candidate_modules, excluded_pre_existing, skipped_module_collisions}, plus doctor when --yes was passed. mode is "dry-run" or "applied". |
adopt never moves, renames, edits, or overwrites any existing file. If a file it
would create already exists, it is skipped and reported "exists, kept" — this
includes README.md, AGENTS.md, CLAUDE.md, and any other file already at that
path. If .gitignore already exists, adopt leaves it untouched and instead prints
a manual follow-up listing the privacy lines (USER.md, MEMORY.md, memory/*,
heartbeat-reports/*) it's missing.
The analyze phase does a light, read-only inventory of the tree (skipping .git,
node_modules, __pycache__, .venv, venv, dist, build, .astro, .next,
target, and dotdirs) and looks for candidate modules: depth 1-2 directories
with 5 or more Markdown files and no index.md/README.md of their own. Each
candidate gets a thin router at modules/<name>/index.md that links to the existing
directory — the directory itself is never touched. If a candidate's name collides
with a module the chosen preset already owns (for example a brownfield codebase/
under the coding preset), no router is created for it and the collision is
reported under skipped_module_collisions; the preset's own starter module doc is
never overwritten by a router.
Adopt uses the same symlink- and out-of-root-hardened write path as init, and an
adopted workspace passes create-vivary doctor and tropo check (adopt writes a
tropo.toml whose exclude list is widened to cover pre-existing brownfield
content, so it isn't flagged as untyped noise).
Pre-existing content inside Vivary's graph folders (modules/, changes/,
decisions/, verification/, gates/) is handled the same way: each
pre-existing Markdown file there is excluded from the typed graph by exact path
(reported under excluded_pre_existing and as a manual follow-up), while
everything adopt itself writes stays graph-visible. A pre-existing modules/
sub-directory without an index.md additionally gets a thin router index (still
only adding a file), because doctor requires every module directory to carry one.
To bring an excluded file into the graph later, add the frontmatter its type
needs and remove its exclude entry from tropo.toml.
# See what adopt would do, without writing anything:
create-vivary adopt . --json
# Apply it:
create-vivary adopt . --yes
# Force a preset instead of the auto-detected one:
create-vivary adopt ~/notes --preset second-brain --yesvivary-cognee ships from the optional vivary-memory-cognee package. It is not part
of core Vivary and does not run unless a workspace explicitly configures
--memory cognee, installs the adapter, and approves provider writes.
vivary-cognee doctor --root . [--json]
vivary-cognee index --root . [--dry-run] [--yes] [--json]
vivary-cognee recall "<query>" --root . [--k N] [--json]
vivary-cognee forget --root . --yes [--json]| Command | What it does |
|---|---|
doctor |
Reports Cognee adapter readiness, typed node count, manifest path, and stale/healthy/unavailable status without importing Cognee runtime. |
index |
Builds privacy-filtered typed Tropo node packets and sends them to Cognee. Requires --yes unless --dry-run is set, and requires memory.cognee.allow_network = true before provider runtime calls. |
recall <query> |
Calls Cognee recall when network/provider runtime is explicitly allowed and the manifest identity matches the current graph, then returns only hits that contain known Vivary node ids from the current typed graph. |
forget |
Removes the workspace dataset from Cognee provider memory. Requires --yes and explicit provider runtime allowance. |
The adapter uses tropo graph truth for ids, types, paths, and edges. Provider state
under .vivary/memory/cognee/ is rebuildable cache, not source truth. The generated
Cognee policy starts with allow_network = false; that is an enforced gate so
doctor/dry-run receipts can prove readiness without importing provider runtime or
making embedding or LLM calls. Runtime provider calls also require api_key_env or
the explicit local-provider setting allow_without_api_key = true. Third-party
Cognee telemetry is disabled by default unless the workspace explicitly sets
allow_telemetry = true.
Approved index replaces the prior workspace-bound dataset, and recall refuses stale
or missing manifests so provider results cannot outrun Tropo graph truth. Dataset
names include a workspace path hash even when a label is configured. Tropo refuses
workspace-local vivary_cognee.py adapter imports for semantic query mode; installed
adapters must resolve outside the workspace and current working tree, and must expose
the hardened vivary-memory-cognee 0.1.1+ adapter contract.
# Human flow — interactive wizard:
create-vivary init my-workspace
# Agent flow — fully non-interactive:
create-vivary init . --preset coding --auto --size large --privacy local --yes --json
# Inspect available optional pieces for a preset:
create-vivary capabilities --preset knowledge-work --json
# Inspect without doing anything:
create-vivary init my-workspace --auto --dry-run --json
# Existing examples:
create-vivary init my-workspace --preset knowledge-work --memory local
create-vivary init my-workspace --preset writing
create-vivary init my-notes --preset second-brain --memory cognee --no-wizard --dry-run --json
create-vivary init my-codebase --preset coding --active-context cocoindex-code
create-vivary doctor my-workspace
# expected for a plain coding workspace: doctor: ok (9 node(s), 28 edge(s), 0 broken)The four presets share the same agent-OS shell and differ only by starter graph. Each
starter module is a directory index (modules/<id>/index.md) so AGENTS can route to a
small surface before deeper context:
| Preset | Module | First change | Verification |
|---|---|---|---|
coding |
codebase |
local-ci-baseline |
local-checks |
second-brain |
knowledge-base |
capture-routine |
retrieval-smoke |
knowledge-work |
workbench + sources |
workbench-first-artifact |
workbench-proof |
writing |
manuscript-system |
draft-review-loop |
editorial-review |
See GETTING-STARTED.md for a first run, HOWTO.md for task recipes, SKILLS.md for the agent skills, and FAQ.md.