diff --git a/Directory.Build.props b/Directory.Build.props
new file mode 100644
index 0000000..c8a3c67
--- /dev/null
+++ b/Directory.Build.props
@@ -0,0 +1,10 @@
+
+
+ $(CULTLIB_ROOT)
+ $(MSBuildThisFileDirectory)..\CultLib
+
+ 42dce3611a81adc5c5fac54cadbaa5637d6022d3
+ C:\Program Files\Git\cmd\git.exe
+ git
+
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
new file mode 100644
index 0000000..46d436a
--- /dev/null
+++ b/Directory.Build.targets
@@ -0,0 +1,30 @@
+
+
+
+
+ <_CultLibReference Include="@(ProjectReference)"
+ Condition="$([System.String]::Copy('%(Filename)').StartsWith('GameCult.')) or '%(Filename)' == 'CultMath'" />
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/README.md b/README.md
index 9392c11..5d56c7f 100644
--- a/README.md
+++ b/README.md
@@ -135,3 +135,14 @@ and contact facts come from Box3D through an explicitly owned Ymir session.
Manual Unity callbacks and Aetheria geometry tests must be structurally unable
to decide the result. Snapshot compatibility calls may use isolated sessions;
they are not allowed to infer or share retained-world identity.
+
+## Building against CultLib
+
+Builds are pinned to CultLib 2.0.0 (tag `cultlib-unity-v2.0.0`, revision `42dce3611a81adc5c5fac54cadbaa5637d6022d3`); the build fails if the CultLib checkout differs or is dirty. Create a pinned worktree and point the build at it:
+
+```powershell
+git -C worktree add --detach cultlib-unity-v2.0.0
+dotnet build -p:CultLibRoot= # or set CULTLIB_ROOT=
+```
+
+Without an override the sibling `..\CultLib` checkout is used and must itself be at that tag.
diff --git a/src/Ymir.Core/Ymir.Core.csproj b/src/Ymir.Core/Ymir.Core.csproj
index 6518910..29683f8 100644
--- a/src/Ymir.Core/Ymir.Core.csproj
+++ b/src/Ymir.Core/Ymir.Core.csproj
@@ -1,7 +1,6 @@
- $(MSBuildThisFileDirectory)..\..\..\CultLib
$(MSBuildThisFileDirectory)..\..\..\Eve