Git¶
get_history¶
Note History. Read-only. Idempotent.
List the commits that touched a note, an attachment, a folder or the whole vault, newest first.
A vault without git history returns no commits.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
path |
string \| null |
null |
A note or attachment path, such as "notes/alpha.md", or a folder, such as "guides"; omit for the whole vault. Give a note's current name: history from before a rename is included. |
since |
string \| null |
null |
Earliest commit date, inclusive: an ISO 8601 time such as "2026-04-01T00:00:00" or a relative date such as "1 week ago"; omit for all history. |
until |
string \| null |
null |
Latest commit date, inclusive, in the same forms as since; omit for no upper bound. |
limit |
integer |
20 |
Maximum commits to return (default 20, at most 100). |
Returns
Envelope dict with the following fields:
- commits (list[dict]): Commit entries, newest-first. Each entry
contains:
sha(str): Full commit SHA (40 hex digits, or 64 in a SHA-256 repository).short_sha(str): 7-character abbreviated SHA.- timestamp (str): ISO 8601 author timestamp.
- author (str): Author name and email, such as
"Name <email>". - message (str): First line of the commit message.
paths_changed(list[str]): Files touched by the commit. Populated for vault-wide queries (path=None) and folder queries (the subtree files the commit touched). Always empty for single-note queries, since the path is already determined by the query arguments; callers know which file the commit touched without needing it echoed back.
- total (int): Count of entries in
commits(always equalslen(commits); does NOT indicate how many commits exist beyond thelimitcap).
Outcomes and errors
- ToolError: If the path is invalid or uses an unsupported extension.
{"path": "notes/alpha.md", "since": "1 week ago", "limit": 5}
Pass a returned sha to read as revision to read the note as it stood then.
get_diff¶
Note Diff. Read-only. Idempotent.
Return how a note or attachment changed from an earlier commit to now, as one unified diff or one per commit.
Pass exactly one of since_sha and since_timestamp; find commits with
get_history. A vault without git history returns an empty diff.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
path |
string |
required | A note or attachment path, such as "notes/alpha.md"; a binary attachment returns a summary of size and renames instead of a patch. |
since_sha |
string \| null |
null |
A commit SHA to diff from, such as from get_history; at least 4 hex digits. |
since_timestamp |
string \| null |
null |
An ISO 8601 time; diffs from the latest commit at or before it. |
per_commit |
boolean |
false |
True for one diff per commit since the starting point, newest first; default false for a single diff. |
limit |
integer \| null |
null |
With per_commit, how many of the most recent commits to include, 1 to 100; omit for all. |
Returns
Envelope dict whose shape depends on per_commit:
- When
per_commit=False:- diff (str): Unified diff from the reference to HEAD. Empty string when there are no changes. May include a truncation notice if the diff exceeds 50 KB.
- When
per_commit=True:- commits (list[dict]): Per-commit entries, newest-first.
Each contains:
sha(str): Full commit SHA.short_sha(str): Abbreviated SHA.- timestamp (str): ISO 8601 author timestamp.
- message (str): First line of commit message.
- diff (str): Unified diff for this commit.
- total (int): Count of entries in
commits(always equalslen(commits); does NOT indicate how many commits exist beyond thelimitcap).
- commits (list[dict]): Per-commit entries, newest-first.
Each contains:
Outcomes and errors
- ToolError: If neither or both reference parameters are supplied, the SHA is invalid, the reference commit is not found, or the path uses an unsupported extension.
{"path": "notes/alpha.md", "since_sha": "9f2c1ab", "per_commit": true, "limit": 3}
git_sync¶
Sync with Git. Changes state, not destructive. Tags: git-managed, write.
Pull from and push to the vault's git remote now; returns what each leg did.
With direction "both" the pull runs first, and a failed pull skips the push.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
direction |
pull \| push \| both |
"both" |
pull, push or both (default). |
dry_run |
boolean |
false |
Report what a pull would do without changing anything; the push leg reports applied false without contacting the remote. |
Returns
Dict with the following fields:
- direction (str): The requested direction, echoed back.
head_sha(str): Local HEAD SHA after the operation. May differ from the pre-call HEAD when the pull leg advanced the branch.- branch (str): Current branch name, or
"HEAD"when the checkout is detached. -
pull (dict | None): Payload from the pull leg, or
Nonewhen direction is"push". Contains: -
applied (bool): true when the pull ran or there was nothing to bring in.
fast_forward(bool): true for a clean fast-forward.commits_pulled(int): commits brought in. It is 0 when the pull rebased or resolved conflicts with sibling files, even though HEAD moved; comparefrom_shaandto_shato see that.from_sha(str),to_sha(str): HEAD before and after the pull.- reason (str, optional):
"fetch_failed","no_remote","non_fast_forward_with_conflicts","rebased","conflicts_resolved_with_siblings"(conflict_fileslists the sibling files),"conflict_resolution_failed"(either HEAD did not move, or the rebase completed and HEAD moved but committing the sibling files failed), or, on a dry run only,"diverged". conflict_files(list[str], optional): the.conflict-mcp-*sibling files written when the pull resolved conflicts.would_apply(bool, dry run only): true when a real pull would change HEAD.-
reindex_failed(bool, optional) andreindex_hint(str, optional): present when the search index could not be refreshed after the pull, so search serves stale results until the next reindex. -
push (dict | None): Payload from the push leg, or
Nonewhen direction is"pull"or when the pull leg failed with direction"both". Contains applied,commits_pushed,remote_sha_before,remote_sha_after, and an optional reason ("dry_run_unsupported","no_remote","non_fast_forward"or"push_failed") and hint. dry_run(bool): Only present whendry_runwas true.
Outcomes and errors
- InvalidRequestError: If the vault is not synced with a remote, so
git_synchas nothing to do.
A pull that met a real conflict and resolved it by keeping both versions:
{"direction": "pull", "head_sha": "4f1c2a9e0b7d3c5f8a6e2d1b9c0a7f3e5d4b2c1a", "branch": "main",
"pull": {"applied": true, "fast_forward": false, "commits_pulled": 0,
"from_sha": "9d8c7b6a5f4e3d2c1b0a9f8e7d6c5b4a3f2e1d0c",
"to_sha": "4f1c2a9e0b7d3c5f8a6e2d1b9c0a7f3e5d4b2c1a",
"reason": "conflicts_resolved_with_siblings",
"conflict_files": ["Notes/2026-05-09.conflict-mcp-20260511-114203.md"]},
"push": null}
The remote's version keeps the note's path. Read the sibling file, merge what it adds, then delete it. Git integration covers the sync modes.