Skip to content

Configuration

kivgraph init writes ~/.config/kivgraph/config.yaml and ~/.config/kivgraph/repositories.yaml. Paths use the ~ notation until they are expanded at load time; after expansion every path key must be absolute.

A configuration written outside the default location is self-contained: its state, its cache and its registry hang from its own directory. A --config in /tmp never publishes over the real graph.

KeyDefaultNotes
version1Configuration schema version.
KeyDefaultNotes
repositories_file~/.config/kivgraph/repositories.yamlThe repository registry document.
KeyDefaultNotes
database_path~/.local/state/kivgraph/graph.lbdbThe canonical LadybugDB database. A published generation lives in its own directory beside it, and carries the graph, the snapshot and the digests that prove they belong together.
backups_path~/.local/state/kivgraph/backupsWhat rollback restores from.

snapshots_path and retain_snapshots no longer exist. Neither ever did anything: nothing was written to the first, and nothing read the second.

A configuration that still carries them loads normally — they are accepted, ignored, and named by kivgraph doctor as config.retired so you can delete them. Rejecting a file that was valid when it was written would be a worse answer than the keys were a mistake.

KeyDefaultNotes
address0.0.0.0:7777Bind of kivgraph ui. Must be a valid host:port. Every non-loopback bind logs what it exposes; there is no authentication.
KeyDefaultNotes
transportstdioThe only accepted value, and a decision rather than a gap. The reason to want a shared transport was memory: every client launching its own server used to mean another private copy of the graph. A server now maps the published snapshot, so the largest part of it is one copy however many are running — see what a second server costs. A client launching its own server is not something to negotiate with the user.
default_limit50Must be positive.
maximum_limit500Must be at least default_limit.
maximum_depth5Must be between 1 and 5.
maximum_visited_nodes25000Must be positive.
KeyDefaultNotes
generated_filesincludeAccepts only include.
unresolved_referencesretainAccepts only retain.
syntax_accelerationtrue
full_rebuild_on_schema_changetrue
fact_cacheonoff, on or verify. verify analyses everything and fails the pass when a servable entry disagrees with the analysis.
fact_cache_path~/.local/state/kivgraph/factcacheOne entry per analysis unit, outside every indexed repository. Must not be empty unless the cache is off.

The two words are not decoration. generated_files and unresolved_references accept exactly one value each because that is exactly what the pass does: it indexes generated files, and it retains every unresolved reference. Accepting another word would promise behaviour no code implements.

KeyDefaultNotes
enabledtrue
debounce_ms150Must be positive.
maximum_batch_ms500Must be at least debounce_ms.
reconciliation_interval10mA Go duration string; must be positive.
KeyDefaultNotes
worker_commandkivgraph-ts-workerMust not be empty.
maximum_workers3Must be positive. Bounds concurrent worker processes.
project_idle_timeout30mMust be positive.
include_unclaimed_sourcesfalseIndexes the .ts/.tsx/.mts/.cts files no project claims, through TypeScript’s inferred project. Those files belong to no program, so they are invisible by construction; enabling this checks them under compiler options Kivgraph chose rather than any the project declared. JavaScript is excluded: whether a .mjs is a source is the project’s allowJs to answer, and this walk resolves no project. See ADR 0050.
KeyDefaultNotes
synthetic_work_file~/.local/state/kivgraph/go.workThe synthetic workspace, outside every indexed repository.
include_testsfalse
build_tags(empty)The constraints every Go load satisfies. No tag may be empty or contain a comma or whitespace. Indexing the Kivgraph repository itself requires ladybug.
allow_networkfalseThe one declared escape from a hermetic pass: lets the go command reach a module proxy.
maximum_loads0Bounds concurrent Go loads; each holds a complete type universe. 0 uses the processor count, capped. Must not be negative.
KeyDefaultNotes
analyzer_commandrust-analyzerMust not be empty. The bundled binary beside the executable wins, then this path, then the PATH.
maximum_workspaces0Bounds concurrent rust-analyzer invocations; each holds a whole Cargo workspace in memory. 0 uses the processor count, capped.
features(empty)Cargo features to activate. Cannot be combined with all_features.
all_featuresfalse
no_default_featuresfalse
cfgs(empty)Additional --cfg values the analysis assumes.
build_scriptstrue
proc_macrostrue
include_teststrueSets cfg(test). Turning it off removes every test item from the graph, and the grammar then reports each one as a declaration the index does not carry.
allow_networkfalseLets cargo reach a registry while the analyzer loads a workspace.
target_directory~/.local/state/kivgraph/rust-targetBuild artifacts of the analysis, outside every indexed repository.
sysrootdiscoverdiscover, none, or a path. Where the standard library is, never whether it enters the graph: loading it is what lets the analyzer resolve Vec at all.
index_sysrootfalsePublishes the standard library as a synthetic provider repository named after the toolchain release, such as rust:1.96.1.

A symbol behind an inactive feature is absent from the graph and reported as unresolved. Feature selection is therefore part of what the graph is, not a performance knob.

With index_sysroot off, four things leave no edge at all: #[derive(...)], an overloaded operator, the ? operator, and every call into the standard library. Each one resolves to a symbol of core, alloc or std, and nothing in the graph declares it. The pass says so, per crate, as CRATE_PROVIDER_NOT_FOUND.

With it on, they become exact edges. It costs one extra analysis unit — around 19.500 symbols and one cold pass per toolchain — and the fact cache serves it afterwards, because the cache fingerprint includes rustc --version. A machine with no toolchain, or one without the rust-src component, indexes its repositories and reports why the standard library is absent; it is never a failure.

Read tools withhold it by default. find_symbol, find_references, trace_dependencies and get_blast_radius accept include_derived: true to ask for it, and naming the repository in repo is a request for it too. graph_status reports what it contributes under derived — including its own unresolved references, which the standard library declares by the thousand — and list_repositories marks the row.

KeyDefaultNotes
metricstrue
tracesfalse

OpenTelemetry integration is optional; exporters and collectors stay disabled by default and the configured provider belongs to the caller.

KeyDefaultNotes
formatjsonjson or text.
levelinfodebug, info, warn or error.
event_log_path~/.local/state/kivgraph/events.jsonlThe append-only record kivgraph logs and kivgraph tool-stats read.

event_log_path is state, not configuration: it holds one JSON object per line describing an indexing pass, a tool call or a server’s lifecycle. It rotates at 8 MiB and keeps one rotation, so the history costs at most 16 MiB and a store that outgrows that drops its oldest records. Deleting it loses history and nothing else. An empty value is refused rather than defaulted, because the default lives in the shared state directory and substituting it would make an isolated configuration write into the real installation.

repositories.yaml carries a version and a list of repositories:

KeyNotes
nameThe identifier. Compared exactly, case included, and carried inside stable keys.
pathAbsolute path to the checkout.
languagesAny of go, typescript, rust. Validated when the registry is written, not only when a pass runs.
manifestsOptional. Explicit manifest paths.
rootsOptional. Explicit analysis roots.
exclusionsOptional. Directories the discovery never walks, and therefore never analyses.
version: 1
repositories:
- name: project
path: /absolute/path/to/project
languages: [go, typescript, rust]
exclusions: [vendor, third_party]