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):
- The create operation failed — skip
- The created item has no ID — skip
subtype = "decision"— skip (decision notes have strict lifecycle and must not be auto-mutated)--no-reweaveflag was passed — skip for this invocation only[reweave] enabled = falsein 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¶
- See Agentic Workflows for how plugins interact with sessions and MCP recipes
- See Configuration for the full ztlctl.toml reference including all plugin config schemas
- See Best Practices for composing plugins with session-based workflows safely
- See Obsidian Starter Kit for setting up the Obsidian integration