README.adoc
June 23, 2026 · View on GitHub
= OSWatcher Procedures :repo: https://github.com/OSWatcher/oswatcher-procedures
Custom Neo4j stored procedures for https://github.com/OSWatcher[OSWatcher] — recursive tree diffing over the merkle graph.
These procedures are deployed as a JAR plugin into Neo4j and power the diff engine used by https://github.com/OSWatcher/neogit[neogit] and https://github.com/OSWatcher/oswatcher-plugins[oswatcher-plugins].
== Procedures
=== oswatcher.diffTreesRecursive
Recursively diffs two nodes in the OSWatcher merkle graph, yielding per-node change records.
[source,cypher]
CALL oswatcher.diffTreesRecursive(
parent_label, // String: node label to traverse (e.g. 'Tree', 'Blob')
base, // String|null: hash of the base node
diffee, // String|null: hash of the diffee node
base_path, // String: starting path prefix (e.g. '/')
filter, // List: child labels to include (empty = all)
max_depth, // Long: depth limit (-1 = unlimited)
with_intermediates, // Boolean: include intermediate nodes
status_filter // List: filter by status (empty = all except UNCHANGED)
)
YIELD status, type, path, old_props, new_props
==== max_depth
[cols="1,3"] |=== | Value | Behaviour
| 0 | Compare nodes themselves only (no children)
| 1 | Immediate children only
| n | n levels deep
| -1 | Unlimited recursion (default)
|===
==== status_filter
[cols="1,3"] |=== | Value | Meaning
| NEW | Node exists only in diffee
| MOD | Node exists in both with different hash
| DEL | Node exists only in base
| UNCHANGED | Node exists in both with same hash (opt-in only)
|===
Empty list returns all statuses except UNCHANGED.
==== Examples
[source,cypher]
// Diff symbols between two Blobs (immediate children only) CALL oswatcher.diffTreesRecursive('Blob', 'hash1', 'hash2', '/', ['Symbol'], 1, false, []) YIELD status, path, old_props, new_props
// Full recursive filesystem tree diff CALL oswatcher.diffTreesRecursive('Tree', 'hash1', 'hash2', '/', [], -1, false, []) YIELD status, path
// Compare two nodes directly (git-log style, no recursion) CALL oswatcher.diffTreesRecursive('Tree', 'hash1', 'hash2', '/', [], 0, false, []) YIELD status, path
// Only show modified and new nodes CALL oswatcher.diffTreesRecursive('Tree', 'hash1', 'hash2', '/', [], -1, false, ['MOD', 'NEW']) YIELD status, path
== Building
Requires Java 17 and Maven 3.9+.
[source,bash]
./mvnw clean package
This produces target/oswatcher-procedures-1.0.0.jar. Deploy it to the plugins/ directory of your Neo4j instance and restart.
== Deployment
Download the latest JAR from https://github.com/OSWatcher/oswatcher-procedures/releases[Releases] and place it in your Neo4j plugins/ directory. No configuration beyond Neo4j's standard plugin loading is required.
== License
Apache License 2.0 — see link:LICENSE[LICENSE].