tropo
A typed-knowledge layer for any folder of Markdown. The filesystem is the schema: a document's type is the folder it lives in, and its metadata is only what can't be derived from where it sits and what it says.
tropo is the elegant successor to a frontmatter typechecker. Where the old
model made every file pay a ceremony tax — type:, created:, updated:,
slug: hand-declared on all of them — tropo derives all of that and asks you to
write down only the irreducible signal. A clean note can have zero
frontmatter and still be fully typed and valid.
Status: working engine (v0.5.4).
tropo.pyimplements spec v1 end-to-end — folder-as-type resolution, derivation, validation, packs, overlays, thesignalreport,fix(de-noise),init, the graph layer (graph/blast/view/plan), typed retrieval (find/query), read-only filesystem inventory (map), and the data layer (file → embedded migration). Cloud adapters are future work. An agent can drive the whole thing via .claude/skills/tropo/SKILL.md.Source:
pyproject.toml; verified: 2026-08-13. See SPEC.md.
Quickstart
python tropo.py init my-vault # scaffold a tropo.toml (--packs dev-project)
python tropo.py check --root examples/vault # validate the included example vault
python tropo.py find "folder as type decision" --root examples/vault --json
python tropo.py map --root examples/vault # read-only filesystem inventory
# Unreleased source-only governed path; core is in the adjacent checkout package.
(
demo="$(python3 -c 'import tempfile; print(tempfile.mkdtemp(prefix="tropo-governed-"))')" &&
trap 'rm -rf -- "${demo:?}"' EXIT &&
python3 -c 'import shutil,sys; shutil.copytree("examples/vault", sys.argv[1], dirs_exist_ok=True)' "${demo:?}" &&
git -C "${demo:?}" init -q &&
git -C "${demo:?}" add -A &&
git -C "${demo:?}" -c user.name="Vivary Quickstart" -c commit.gpgsign=false \
-c user.email="quickstart@vivary.invalid" commit -qm "governed quickstart" &&
PYTHONPATH=../core python3 tropo.py find "folder as type decision" \
--root "${demo:?}" --governed --max-claims 12 --json
)
Requires Python 3.11+ (stdlib tomllib) and the first-party vivary-core>=0.2.7
contract seam. Neither package adds third-party runtime dependencies. Optional
extras: python -m pip install "vivary-tropo[embedded]" for LanceDB embedded storage and
backend-level experiments. Plain tropo find and default tropo query read the typed
graph directly without providers, network calls, or indexing. tropo query --mode
vector uses
zero-dependency computed vectors for file-backed workspaces; when optional embedded
storage is configured and current migrated vectors exist, it uses those stored rows
through the embedded backend. In both cases it preserves type/path/edge filters and
falls back to typed text search with an explicit JSON status when the vector index is
not trustworthy. tropo query --mode semantic is an optional-provider bridge: it only
runs when .vivary/memory.toml enables a supported semantic-memory provider,
currently the separate vivary-memory-cognee package. Tropo core does not bundle
Cognee, network calls, or provider indexing.
Cloud extras are reserved for future adapter work.
tropo migrate --from file --to embedded --json reports embedding persistence
explicitly. With no [storage.embedding] table, rows stay plain typed nodes. With
enabled = true and provider = "local-hash", migrated rows include a vector plus
source and embedding fingerprints, so stored vector query can refuse stale rows
without re-chunking the workspace. Invalid embedding config and unsafe embedded
storage paths fail before any embedded backend write. Real file-to-embedded migration
replaces the embedded node snapshot, so deleted, renamed, newly excluded, or
vector-schema-changed nodes do not leave stale embedded rows behind.
Built-in packs are embedded in the single-file engine, so installed wheels can resolve
starter packs without a repo-local packs/ directory. Workspace-local
.tropo/packs/<name>.toml files still take precedence.
TOML config and frontmatter parsing tolerate a single leading UTF-8 BOM, which keeps
Windows-created files from failing to load or being misread as body-only documents.
tropo view --out keeps generated HTML under the tropo root, rejects symlink targets,
and replaces output files without mutating hard-linked files outside the workspace.
For local debugging, pass --receipt PATH or set VIVARY_RECEIPT_LOG=PATH to append
a dependency-free JSONL run receipt. Receipts stay local and record only command
envelope data such as tool version, command, flag names, exit code, duration, Python,
and platform; they do not capture stdout, stderr, file contents, raw query text,
target ids, or paths.
tropo find is the friendly context-compression command: it returns a short packet of
typed nodes/files to open first, with reasons, snippets, and an approximate token
budget. tropo query is the lower-level filtered search primitive; it can filter by
type, path glob, or outbound edge and explain whether a match came from id/title,
frontmatter, path, body, edge context, or typed vectors. Semantic mode returns
provider hits as typed Vivary node ids instead of opaque chunks.
Add --governed to tropo find to opt into the first vivary-core adapter: a
read-only workspace scan becomes a bounded, fingerprinted Task Capsule. Plain
tropo find remains unchanged. The canonical flag rules, safety boundary, evidence
shape, privacy behavior, and bounds live in the
command reference.
Search mode mental model:
| Mode | Boundary |
|---|---|
text |
Default deterministic graph search; no setup. |
vector |
Local fuzzy ranking over typed graph nodes; no provider and falls back to text without explicit local vector policy. |
semantic |
Optional provider bridge, filtered back to known typed Vivary node ids. |
Overlays — tighten a subtree
Drop a tropo.toml in any subdirectory to add stricter rules for that subtree
only (a new required field, a narrowed enum, a nested type). It may only add
constraints, never remove them — so you can always reason about a document
top-down. See examples/vault/projects/tropo/tropo.toml,
which requires every decision under that project to record its deciders.
The one idea
people/jeff.md → type = person (the folder says so)
projects/tropo/README.md → type = project (nearest registered ancestor)
meetings/2026-06-12.md → type = meeting
No type: field. No hand-written dates. The path carries the type; git and
the filesystem carry the dates; the first # H1 carries the title. What's
left in frontmatter is the handful of fields that are genuinely irreducible —
a person's relationship, a meeting's attendees, a decision's status.
Frontmatter is the exception, not the rule.
Before / after
A person note, the old way:
---
type: person
created: 2026-06-12
updated: 2026-06-12
slug: jeff
title: Jeff
relationship: self
---
# Jeff
The tropo way — same information, no noise:
---
relationship: self
---
# Jeff
type comes from people/. created/updated come from git. slug comes from
the filename. title comes from the H1. Only relationship is irreducible, so
only relationship is written down.
Why it's not just a second-brain tool
The config resolves by walking up the tree — like git, tsconfig, or
pyproject.toml. Drop one tropo.toml at a repo root and that repo gains a
typed-knowledge layer: decisions/, runbooks/, specs/, adr/ become
enforceable document types with derived metadata and CI-checkable rules. Same
engine, same grammar, whether it's a personal vault or a codebase's docs/.
tropo is a portable convention plus a tiny engine, not anyone's particular vault. Types ship as composable packs; a subfolder can overlay tighter rules without redefining anything.
Graphify-friendly repo maps
Use the repo-graph pack when a repository or control vault wants Markdown
notes that double as Graphify-readable nodes:
packs = ["repo-graph"]
It defines folder-backed types for modules/, changes/, decisions/,
verification/, and gates/, while allowing explicit graph fields such as
id, related_modules, related_changes, and verification. This is a
deliberate bridge: Tropo validates the node shape, Markdown/wiki links remain
human-readable, and Graphify can index the relationships.
For multi-agent coordination, add the opt-in coordination pack:
packs = ["repo-graph", "coordination"]
It declares top-level assignee = "string" without changing the default workspace
schema. exo claim <id> --agent <handle> uses that field for graph-native work
ownership.
Design tenets
- Signal over noise. If a value can be derived, never make a human write it.
- Location is type. The directory tree is the type hierarchy.
- Tighten, never loosen. Overlays and packs may add constraints, not remove them.
- Dependency-light, CI-clean. Tropo stays a single-file engine with one first-party core seam and honest exit codes.
Layout
tropo/
├─ README.md you are here
├─ SPEC.md the normative model + config format reference
├─ tropo.toml the project's own (dogfooded) config
└─ examples/
└─ vault/ a tiny tree showing zero-frontmatter notes
License
MIT — see LICENSE.
Website & docs: https://vivary.vercel.app/
Release files for vivary-tropo 0.5.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vivary_tropo-0.5.4.tar.gz | 68.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vivary_tropo-0.5.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 131.5 kB
Release files / vivary_tropo-0.5.4.tar.gz
| Download URL | vivary_tropo-0.5.4.tar.gz |
|---|---|
| Size | 68.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
70c2597f7e82672b5494b9f4d636bfd055146e8588efcfcd82bc8ea1edb032a5
|
|
BLAKE2b-256 checksum How to use checksums |
6fdcc4e6bfb08150bec77902f3bab4bd5e342281d5a501dd49f75d06db8b64cc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / vivary_tropo-0.5.4-py3-none-any.whl
| Download URL | vivary_tropo-0.5.4-py3-none-any.whl |
|---|---|
| Size | 63.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
66821760d9d8e7b2f91f9ee6f1b555f04005baca4624f341d9dce1a2de03f006
|
|
BLAKE2b-256 checksum How to use checksums |
84454cba8d9a5b204bb0a83a49bc729ab96738dfa0557e018aee6c84d4984919
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.21 {"installer":{"name":"uv","version":"0.11.21","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|