Reserved Paths in Claude-Obsidian: What User-Authored Bundles Cannot Overwrite
Claude-Obsidian enforces data integrity by maintaining a hard-coded list of reserved paths in claude_obsidian/helpers.py that user-authored bundles are strictly forbidden from modifying or replacing.
Claude-Obsidian is an agent-skill framework that constructs Obsidian-flavoured knowledge bases from Claude model responses. To protect core metadata and ensure deterministic replay of knowledge updates, the repository implements an immutability layer that prevents writes to critical system files. Understanding these reserved paths is essential for developers extending the tool or creating custom vault integrations.
What Are Reserved Paths in Claude-Obsidian?
Reserved paths are filesystem locations within a Claude-Obsidian vault that the system protects from modification by user-authored bundles. These paths contain essential metadata, provenance ledgers, seed templates, and helper scripts that maintain the structural integrity of the knowledge base. According to the source code in claude_obsidian/helpers.py, any attempt to write to these locations triggers a validation error and aborts the transaction.
The validation logic lives in the RESERVED_PATHS constant and the accompanying is_reserved_path() function. When a bundle is submitted, the validate_bundle() function checks the target path against this list, ensuring that immutable components remain untouched during normal operations.
The Complete List of Reserved Paths
The RESERVED_PATHS list in claude_obsidian/helpers.py defines five specific locations that bundles cannot overwrite:
.raw/.manifest.json– The global manifest that records immutable source payloads and tracks the provenance of ingested data..vault-meta/keep-alive.sh– A helper script designed for long-running processes that must remain unchanged to ensure vault stability.wiki/meta/ledgers/– The directory containing signed provenance ledgers for knowledge claims and audit trails.wiki/.gitkeep– A placeholder file that preserves thewiki/directory structure in version control systems.templates/– The entire template tree containing seed vault content; this directory and all sub-paths are protected as immutable seed data.
The system performs path normalization using pathlib.Path.as_posix() to ensure cross-platform compatibility when checking these reserved locations.
How Bundle Validation Works
The validation pipeline relies on two core functions defined in claude_obsidian/helpers.py:
is_reserved_path(path: str) -> bool – This function normalizes the input path to POSIX style and checks it against the RESERVED_PATHS list. It returns True if the path matches exactly or if it resides within a reserved directory tree (detected via startswith logic).
validate_bundle(bundle: Dict[str, Any]) -> None – This function extracts the "path" field from a bundle dictionary and invokes is_reserved_path(). If the path is reserved, the function raises a ValueError with the message "Attempt to write to reserved path: {path}", preventing the transaction from committing.
from claude_obsidian.helpers import validate_bundle, is_reserved_path
# Check if a path is reserved
print(is_reserved_path(".raw/.manifest.json")) # True
print(is_reserved_path("wiki/notes/Paris.md")) # False
Practical Examples: Validating Bundle Writes
When building custom integrations, you must ensure your bundles target writable locations. The following examples demonstrate both valid and invalid operations:
Valid Bundle: Writing to the Wiki
from claude_obsidian.helpers import validate_bundle
# This succeeds – the path is not reserved
valid_bundle = {
"path": "wiki/Paris.md",
"content": "# Paris\n\nThe capital of France."
}
validate_bundle(valid_bundle) # No exception raised
Invalid Bundle: Attempting to Overwrite the Manifest
from claude_obsidian.helpers import validate_bundle
# This fails – .raw/.manifest.json is reserved
invalid_bundle = {
"path": ".raw/.manifest.json",
"content": "{}"
}
try:
validate_bundle(invalid_bundle)
except ValueError as e:
print(e) # Output: Attempt to write to reserved path: .raw/.manifest.json
Invalid Bundle: Writing Under the Templates Tree
# This also fails – the entire templates/ directory is protected
template_bundle = {
"path": "templates/custom/page.md",
"content": "# Custom Template"
}
validate_bundle(template_bundle) # Raises ValueError
Summary
- The reserved paths in Claude-Obsidian are hard-coded in
claude_obsidian/helpers.pywithin theRESERVED_PATHSconstant. - Protected locations include the manifest file (
.raw/.manifest.json), vault metadata scripts (.vault-meta/keep-alive.sh), provenance ledgers (wiki/meta/ledgers/), directory placeholders (wiki/.gitkeep), and the entire seed template tree (templates/). - The
is_reserved_path()function checks for exact matches and sub-directory relationships using POSIX-style path normalization. - The
validate_bundle()function enforces these restrictions by raising aValueErrorwhen any bundle attempts to write to a reserved location. - These protections ensure immutable source payloads remain intact and the vault structure maintains deterministic behavior across transactions.
Frequently Asked Questions
What happens if a bundle tries to write to a reserved path?
According to the implementation in claude_obsidian/helpers.py, the validate_bundle() function raises a ValueError with the message "Attempt to write to reserved path: {path}". This error aborts the current transaction, preventing any modifications to the protected file or directory.
Can I modify the keep-alive.sh script in my vault?
No, the .vault-meta/keep-alive.sh script is explicitly listed in RESERVED_PATHS to ensure long-running processes remain stable. If you need custom process management, you should create new scripts in unreserved locations such as wiki/scripts/ or .vault-meta/custom/ rather than modifying the reserved default.
Why is the templates directory protected?
The templates/ directory contains the seed data used to initialize fresh vaults during the claude_obsidian init command. Protecting this entire tree ensures that every new vault starts with a consistent, known-good structure. User-authored bundles should write content to wiki/ or other user-space directories rather than attempting to replace the core template files.
How do I add custom metadata if the meta directories are reserved?
While wiki/meta/ledgers/ is reserved for system provenance tracking, you can create custom metadata structures in unreserved paths such as wiki/meta/custom/ or wiki/.meta/. The reserved status applies only to the specific paths listed in RESERVED_PATHS, not to the entire wiki/ hierarchy.
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 →