# How the Claude-Obsidian Mutation Protocol Works: A 5-Step Transaction Workflow

> Explore the Claude-Obsidian mutation protocol workflow. Discover how pre-condition hashing, parallel drafting, and atomic bundling ensure safe and auditable vault updates in 5 steps.

- Repository: [Agrici.Daniel/claude-obsidian](https://github.com/AgriciDaniel/claude-obsidian)
- Tags: deep-dive
- Published: 2026-08-25

---

**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](https://github.com/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)](https://github.com/AgriciDaniel/claude-obsidian/blob/main/AGENTS.md#L49-L55), 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`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/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`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py) module implements defensive guards to uphold the recoverable-operation contract. According to the [module header (lines 1-6)](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py#L1-L6), 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/transaction` and `.vault-meta/mutation.lock`, ensuring user-supplied bundles cannot tamper with ledger or lock files ([transaction.py lines 63-71](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py#L63-L71)).

- **Operation Type Whitelisting**: Transactions declare their scope (e.g., `wiki-only` vs. `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](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py#L92-L99)).

- **Resource Limits**: Hard constraints on bundle size prevent exhaustion attacks. The system enforces `MAX_TRANSACTION_FILE_BYTES` and `MAX_TRANSACTION_WRITES` thresholds during validation ([transaction.py lines 38-45](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py#L38-L45)).

## 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)

```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

```bash

# 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`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/AGENTS.md) | Human-readable specification of the five-step mutation workflow | [View AGENTS.md](https://github.com/AgriciDaniel/claude-obsidian/blob/main/AGENTS.md) |
| [`claude_obsidian/transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py) | Core engine implementing the durable journal, pre-condition hashing, and rollback logic | [View transaction.py](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py) |
| [`scripts/claude-obsidian.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/scripts/claude-obsidian.py) | CLI entry point for bundle inspection, lock acquisition, and transaction execution | [View claude-obsidian.py](https://github.com/AgriciDaniel/claude-obsidian/blob/main/scripts/claude-obsidian.py) |
| [`claude_obsidian/ledgers.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/ledgers.py) | Provenance ledger management for claim and source tracking | [View ledgers.py](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/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.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude-obsidian.py)** CLI and **[`transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/transaction.py)** module 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](https://github.com/AgriciDaniel/claude-obsidian/blob/main/AGENTS.md) and implemented in the [`transaction.py`](https://github.com/AgriciDaniel/claude-obsidian/blob/main/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](https://github.com/AgriciDaniel/claude-obsidian/blob/main/claude_obsidian/transaction.py#L1-L6).

### 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.