How the Claude-Obsidian Mutation Protocol Works: A 5-Step Transaction Workflow
The Claude-Obsidian mutation protocol treats every knowledge change as a recoverable transaction that uses pre-condition hashing, parallel drafting, and atomic bundle application to ensure safe, auditable vault updates.
The AgriciDaniel/claude-obsidian repository implements a robust transaction system for Obsidian vaults. Unlike standard file operations that risk partial writes or race conditions, this mutation protocol guarantees recoverable, atomic-like updates through a strict five-step workflow defined in the project documentation.
Understanding the Five-Step Mutation Protocol
According to the AGENTS.md specification (lines 49-55), every logical change to the vault follows a deterministic pipeline that separates preparation from execution. This design prevents corruption and enables deterministic rollback.
Step 1: Read and Hash (Pre-condition Snapshot)
Before any modification, the system reads all target files and records their SHA-256 hashes. This creates an immutable pre-condition snapshot that validates the filesystem state has not changed underneath the operation. If a hash mismatch occurs during application, the transaction aborts to prevent overwriting external changes.
Step 2: Parallel Drafting
One or more parallel workers generate draft versions of files together with evidence artifacts (such as provenance data or claim-ledger entries). Workers operate entirely in memory and never write directly to the vault. This isolation ensures that partial failures during drafting never corrupt the actual vault state.
Step 3: Bundle Merge
Drafts and evidence merge into a single portable JSON document conforming to the claude-obsidian.transaction.v1 schema. This transaction bundle captures the entire intended mutation, including target paths, content hashes, and metadata, making it suitable for inspection, version control, or delayed application.
Step 4: Inspection and Application
The bundle undergoes optional validation by human reviewers or automated tools. Upon approval, the claude-obsidian.py CLI performs the actual filesystem writes in a coordinated step. As implemented in the transaction module, this phase acquires an exclusive mutation lock, verifies pre-condition hashes against current disk state, and executes atomic per-file replacements using temporary files and rename operations.
Step 5: Reporting and Ledger Updates
After successful writes, the CLI outputs an operation ID (e.g., 20260825-7f3c) and a list of exact paths modified. The system appends this information to the vault's durable journal and relevant ledgers, creating a permanent audit trail for provenance queries.
Safety Mechanisms in the Transaction System
The claude_obsidian/transaction.py module implements defensive guards to uphold the recoverable-operation contract. According to the module header (lines 1-6), multi-file updates are not truly atomic on standard filesystems, so Claude-Obsidian supplies stronger guarantees through explicit safety measures:
-
Reserved Write Paths: The system protects internal bookkeeping locations such as
.vault-meta/transactionand.vault-meta/mutation.lock, ensuring user-supplied bundles cannot tamper with ledger or lock files (transaction.py lines 63-71). -
Operation Type Whitelisting: Transactions declare their scope (e.g.,
wiki-onlyvs.wiki-and-raw), and the engine validates that all paths in the bundle match the declared operation type, preventing scope escalation (transaction.py lines 92-99). -
Resource Limits: Hard constraints on bundle size prevent exhaustion attacks. The system enforces
MAX_TRANSACTION_FILE_BYTESandMAX_TRANSACTION_WRITESthresholds during validation (transaction.py lines 38-45).
Code Examples: Building and Applying Transaction Bundles
The following snippets demonstrate how to construct a valid mutation bundle programmatically and apply it via the CLI.
Building a Transaction Bundle (Python)
import json
import hashlib
from pathlib import Path
from claude_obsidian.transaction import BUNDLE_SCHEMA
def sha256_of(path: Path) -> str:
return hashlib.sha256(path.read_bytes()).hexdigest()
# 1. Record pre-condition hashes
targets = {
"wiki/notes/example.md": sha256_of(Path("wiki/notes/example.md")),
}
# 2. Prepare drafts (in-memory edits)
drafts = {
"wiki/notes/example.md": "# Updated Title\n\nNew content here.\n"
}
# 3. Optional evidence (claim-ledger entry)
evidence = {
"wiki/meta/ledgers/claim-ledger.json": {
"operation": "save",
"file": "wiki/notes/example.md",
"timestamp": "2026-08-25"
}
}
# 4. Assemble the bundle
bundle = {
"schema": BUNDLE_SCHEMA,
"operation": "save",
"targets": targets,
"drafts": drafts,
"evidence": evidence,
}
# Write bundle for CLI consumption
Path("my_bundle.json").write_text(json.dumps(bundle, indent=2))
print("Bundle ready → my_bundle.json")
Applying the Bundle via CLI
# Inspect the bundle before applying (optional)
python scripts/claude-obsidian.py inspect my_bundle.json
# Apply the transaction atomically
python scripts/claude-obsidian.py apply my_bundle.json
# Output example:
# ✅ Operation ID: 20260825-7f3c
# ✏️ Modified: wiki/notes/example.md
# 📜 Ledger updated: wiki/meta/ledgers/claim-ledger.json
The apply command executes the critical section: it verifies pre-condition hashes, acquires the .vault-meta/mutation.lock, writes drafts to temporary files, performs atomic renames, and updates the transaction journal. If any step fails, the transaction module triggers a rollback, restoring the vault to its pre-transaction state.
Core Source Files and Architecture
| File | Purpose | Link |
|---|---|---|
AGENTS.md |
Human-readable specification of the five-step mutation workflow | View AGENTS.md |
claude_obsidian/transaction.py |
Core engine implementing the durable journal, pre-condition hashing, and rollback logic | View transaction.py |
scripts/claude-obsidian.py |
CLI entry point for bundle inspection, lock acquisition, and transaction execution | View claude-obsidian.py |
claude_obsidian/ledgers.py |
Provenance ledger management for claim and source tracking | View ledgers.py |
Summary
- The Claude-Obsidian mutation protocol guarantees recoverable vault updates through a five-step transaction pipeline: hash recording, parallel drafting, bundle merging, atomic application, and ledger reporting.
- Pre-condition SHA-256 hashes detect conflicting changes before writes occur, preventing silent overwrites.
- Reserved paths and size limits enforce security boundaries and resource protection during transaction processing.
- The
claude-obsidian.pyCLI andtransaction.pymodule coordinate exclusive locks, atomic file replacement, and deterministic rollback to maintain vault integrity.
Frequently Asked Questions
What is the Claude-Obsidian mutation protocol?
The mutation protocol is a transaction system that treats every vault modification as a recoverable operation. It ensures that changes are atomic-like, auditable, and isolated from concurrent access by using pre-condition hashes, exclusive locks, and durable journals. This protocol is defined in AGENTS.md and implemented in the transaction.py module.
How does Claude-Obsidian ensure atomic-like behavior without native filesystem transactions?
Because standard filesystems lack true multi-file atomic commits, the system uses a mutation lock (.vault-meta/mutation.lock) to enforce exclusive access. It writes changes to temporary files and uses atomic rename operations to swap them into place. If the process crashes mid-operation, the durable journal enables deterministic recovery or rollback on restart, as detailed in the transaction.py header.
What happens if a transaction fails mid-way?
The transaction engine detects failures during the verification or write phase. If pre-condition hashes mismatch or a filesystem error occurs, the system aborts the operation and rolls back any partially applied changes using the data recorded in the transaction journal. This preserves the vault's integrity and prevents "half-written" states.
How do I create a transaction bundle programmatically?
Import the BUNDLE_SCHEMA constant from claude_obsidian.transaction, construct a dictionary containing targets (path-to-hash mappings), drafts (new file contents), and optional evidence (ledger entries), then serialize it to JSON. Pass this file to scripts/claude-obsidian.py apply to execute the mutation while respecting all safety constraints and atomicity guarantees.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →