ztlctl ships two built-in plugins that run automatically in the background: the Git plugin for automatic version control and the Reweave plugin for automatic link discovery. Both are enabled by default. This page explains exactly what they do, when they run, and how to configure them.

All plugin config lives under the [plugins.<name>] TOML key in ztlctl.toml. Config is validated at load time against the plugin's declared Pydantic schema (via get_config_schema hookspec). See Configuration for the full ztlctl.toml reference.

Git Plugin

The Git plugin provides automatic version control for vault operations. When you create a note, the plugin stages the file and — depending on configuration — either commits immediately or batches the commit for session close.

Prerequisites

Note

The Git plugin requires git to be installed and available on your PATH. If git is not found, the plugin logs a debug message and continues silently — vault operations never fail due to git errors.

Verify git is available:

git --version

What Gets Committed Automatically

Every vault operation that creates or modifies a markdown file triggers a git stage. Commit timing depends on the batch_commits setting (see Configuration below).

Action Commit Message Format
ztlctl create note feat: create note {id} — {title}
ztlctl create reference feat: create reference {id} — {title}
ztlctl create task feat: create task {id} — {title}
ztlctl update docs: update {id} ({fields_changed})
ztlctl archive docs: close {id} — {summary}
ztlctl session close docs: session {id} — N created, N updated
ztlctl init feat: initialize vault '{name}'

Operations that are no-ops for the Git plugin: reweave run, session start, check check, check rebuild. These do not stage or commit any files.

Batch Mode vs Immediate Mode

Mode Behavior When to use
Batch (default) Files are staged on each operation; one commit is made at session close Session-based workflows — clean history with one commit per session
Immediate Files are staged AND committed after every individual operation Headless or no-session workflows — each note creation is its own commit

Warning

In batch mode, creating notes outside an active session stages files but never commits them — the commit trigger is session close. If you work without sessions, set batch_commits = false.

What git status looks like in batch mode (before session close):

$ git status
On branch develop
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   notes/ZTL-0001.md
        new file:   notes/ZTL-0002.md
        modified:   notes/ZTL-0003.md

After ztlctl session close, all staged changes are committed in one operation:

docs: session LOG-0001 — 2 created, 1 updated

Git Plugin Configuration

In ztlctl.toml:

[plugins.git]
enabled = true
batch_commits = true      # true = commit at session close, false = commit immediately
auto_push = true          # push to remote on session close
auto_ignore = true        # write .gitignore during vault init

All config fields (sourced from GitConfig model in config/models.py):

Field Default Meaning
enabled true Enable or disable the entire plugin
batch_commits true Batch all changes into one session-close commit
auto_push true Push to remote after session-close commit
auto_ignore true Write .gitignore during ztlctl init
branch "develop" Target branch (informational — plugin does not enforce branch)
commit_style "conventional" Commit message format (currently only "conventional")

The auto-generated .gitignore excludes:

# ztlctl vault gitignore
.ztlctl/backups/
*.db-journal

Common Scenarios

Disable automatic commits entirely:

[plugins.git]
enabled = false

Use immediate commits (one commit per note):

[plugins.git]
batch_commits = false

Push to remote automatically on session close:

[plugins.git]
auto_push = true

Reweave Plugin

The Reweave plugin automatically discovers connections for new notes and references the moment they are created. It runs the full 4-signal scoring algorithm against all existing content and creates graph edges for items above the threshold.

What It Does

When you create a note or reference, the Reweave plugin immediately calls the reweave pipeline on the new item. This means your vault's link graph is always up to date without any manual ztlctl reweave run call.

# When you run this:
ztlctl create note "Attention mechanisms" --tags ml/transformers

# The Reweave plugin automatically runs the equivalent of:
ztlctl reweave run --content-id ZTL-0042
# → finds related notes via BM25 + tag overlap + graph proximity + shared topic
# → creates edges for items scoring above 0.6 (default threshold)

When It Runs (and When It Doesn't)

Fires for: create note, create reference only.

Does not fire for: create task, update, archive, session close, or reweave run (manual reweave is not re-triggered).

Skip conditions (checked in order):

  1. The create operation failed — skip
  2. The created item has no ID — skip
  3. subtype = "decision" — skip (decision notes have strict lifecycle and must not be auto-mutated)
  4. --no-reweave flag was passed — skip for this invocation only
  5. [reweave] enabled = false in config — skip globally

Note

Decision notes (ztlctl create note --subtype decision) are intentionally excluded from auto-reweave. Decision notes represent deliberate choices and must not be auto-linked by background processes. Run ztlctl reweave run --content-id {id} manually if you want to connect a decision note.

4-Signal Scoring

The reweave algorithm scores candidate links using four signals:

Signal Default Weight What It Measures
BM25 lexical similarity 0.35 Shared vocabulary between note bodies
Jaccard tag overlap 0.25 Proportion of tags in common
Graph proximity 0.25 How closely connected via existing edges
Shared topic directory 0.15 Whether notes share a topic routing prefix

A link is created when the combined score exceeds min_score_threshold (default: 0.6).

Reweave Plugin Configuration

In ztlctl.toml:

[reweave]
enabled = true
min_score_threshold = 0.6   # raise to 0.75 for fewer, higher-quality links
max_links_per_note = 5      # raise for denser graphs
lexical_weight = 0.35
tag_weight = 0.25
graph_weight = 0.25
topic_weight = 0.15

All config fields (sourced from ReweaveConfig model in config/models.py):

Field Default Meaning
enabled true Global enable/disable for auto-reweave
min_score_threshold 0.6 Minimum combined score (0.0–1.0) to create a link
max_links_per_note 5 Maximum new links per auto-reweave run
lexical_weight 0.35 BM25 signal weight
tag_weight 0.25 Tag overlap signal weight
graph_weight 0.25 Graph proximity signal weight
topic_weight 0.15 Topic directory signal weight

Weights do not need to sum to 1.0 — they are relative, not normalized.

Common Scenarios

Disable auto-reweave for a single note:

ztlctl create note "Quick capture" --no-reweave

Disable auto-reweave globally:

[reweave]
enabled = false

Tune for fewer, higher-quality links:

[reweave]
min_score_threshold = 0.75
max_links_per_note = 3

Emphasize tag-based connections (lower lexical weight):

[reweave]
lexical_weight = 0.20
tag_weight = 0.45

Run reweave manually for an existing note:

ztlctl reweave run --content-id ZTL-0042

Anti-Patterns

Anti-Pattern: Enabling auto_push without reviewing commits first

With auto_push = true, every session close triggers a git push to the remote. If your vault has sensitive or draft content that should not leave your local machine, set auto_push = false until you have reviewed the staged content. Use git log --oneline -5 after session close to inspect what was committed before enabling auto-push in production workflows.

Anti-Pattern: Setting min_score_threshold too low

Setting min_score_threshold below 0.4 will create noise — every pair of notes that shares one or two tokens in common will receive a link. Low-quality links reduce the signal-to-noise ratio in graph related, graph rank, and reweave-based session close enrichment. Start at 0.6 (default) and lower incrementally only if the graph is too sparse after a month of use.

Anti-Pattern: Disabling the git plugin after existing history

If you disable [plugins.git] enabled = false after already using the vault with git enabled, outstanding staged changes are left uncommitted forever. Future ztlctl session close calls will not commit them. If you want to stop tracking history mid-use, manually commit all staged files (git commit -am "chore: disable git plugin") before setting enabled = false.

Anti-Pattern: Using [plugins.git] toml key for the Reweave config section

Reweave plugin config lives under [reweave] directly (not [plugins.reweave]). The Reweave plugin is a built-in whose config is managed by the top-level ReweaveConfig model, while the Git plugin uses the extensible [plugins.git] path under PluginsConfig. Mixing the two causes silent config fallback to defaults.


Next Steps