Summary
OpenKnowledge can end up with nested projects when a child project is initialized first and an ancestor is initialized later. ok init detects an existing .ok only by walking upward from the requested directory; initializing an ancestor does not detect descendant .ok projects inside its content scope.
This creates ambiguous project resolution and makes ok deinit <path> potentially surprising because it may resolve upward and remove an ancestor project rather than the directory the user believes they selected.
Environment
- OpenKnowledge CLI:
0.29.1
- macOS
- OK Desktop
Reproduction / observed layout
The machine ended up with this structure:
/Users/example/.ok # ancestor OK project
/Users/example/Project/
└── kpr-oppo-knowledge-base/
└── .ok # independent child OK project
The ancestor project's content.dir pointed into Project (the Desktop UI opened/displayed the child knowledge content), while kpr-oppo-knowledge-base also retained a complete independent OK setup (.ok, .okignore, MCP configs, project skills, and .git/ok).
This can happen with the following ordering:
- Initialize
Project/kpr-oppo-knowledge-base as an OK project.
- Later initialize
/Users/example as another OK project and set its content.dir to Project or a descendant.
- The ancestor initialization succeeds because it does not scan the selected content scope for descendant
.ok directories.
Surprising deinit behavior
Running:
ok deinit /Users/example/Project --dry-run --json
reported:
[ok] Using OpenKnowledge project at /Users/example
and planned removal of /Users/example/.ok plus its project-level MCP entries and skills. The requested path and resolved project root were different. With --yes, the ancestor project was removed while the nested child project remained.
The resolver behavior is internally consistent (nearest ancestor .ok), but it is easy for a user to misunderstand—especially when OK Desktop displays an opened folder/content directory rather than clearly distinguishing the project root and content.dir.
Risks
- The same Markdown tree may be watched/indexed by both ancestor and child projects.
- Project identity differs depending on the current working directory.
- Desktop project name/opened folder, project root, and content directory can appear to be the same concept when they are not.
deinit <path> can remove configuration above the requested path without an explicit mismatch confirmation.
Suggested safeguards
-
During ok init, scan the proposed content.dir for descendant .ok directories and warn or refuse unless explicitly overridden.
-
Reject or warn when changing content.dir to a tree containing another OK project.
-
Make parent watchers automatically exclude nested OK project roots.
-
Before deinit, always show both:
Requested path: /Users/example/Project
Resolved project root: /Users/example
-
When those paths differ, require an explicit confirmation or a flag such as --project-root /Users/example; consider not allowing --yes alone to bypass this mismatch protection.
-
In OK Desktop, display the project root and content directory separately.
Expected behavior
OpenKnowledge should either prevent nested project configurations or handle them as an explicit, well-defined feature. Destructive project operations should make ancestor resolution unmistakable before applying changes.
Summary
OpenKnowledge can end up with nested projects when a child project is initialized first and an ancestor is initialized later.
ok initdetects an existing.okonly by walking upward from the requested directory; initializing an ancestor does not detect descendant.okprojects inside its content scope.This creates ambiguous project resolution and makes
ok deinit <path>potentially surprising because it may resolve upward and remove an ancestor project rather than the directory the user believes they selected.Environment
0.29.1Reproduction / observed layout
The machine ended up with this structure:
The ancestor project's
content.dirpointed intoProject(the Desktop UI opened/displayed the child knowledge content), whilekpr-oppo-knowledge-basealso retained a complete independent OK setup (.ok,.okignore, MCP configs, project skills, and.git/ok).This can happen with the following ordering:
Project/kpr-oppo-knowledge-baseas an OK project./Users/exampleas another OK project and set itscontent.dirtoProjector a descendant..okdirectories.Surprising
deinitbehaviorRunning:
reported:
and planned removal of
/Users/example/.okplus its project-level MCP entries and skills. The requested path and resolved project root were different. With--yes, the ancestor project was removed while the nested child project remained.The resolver behavior is internally consistent (nearest ancestor
.ok), but it is easy for a user to misunderstand—especially when OK Desktop displays an opened folder/content directory rather than clearly distinguishing the project root andcontent.dir.Risks
deinit <path>can remove configuration above the requested path without an explicit mismatch confirmation.Suggested safeguards
During
ok init, scan the proposedcontent.dirfor descendant.okdirectories and warn or refuse unless explicitly overridden.Reject or warn when changing
content.dirto a tree containing another OK project.Make parent watchers automatically exclude nested OK project roots.
Before
deinit, always show both:When those paths differ, require an explicit confirmation or a flag such as
--project-root /Users/example; consider not allowing--yesalone to bypass this mismatch protection.In OK Desktop, display the project root and content directory separately.
Expected behavior
OpenKnowledge should either prevent nested project configurations or handle them as an explicit, well-defined feature. Destructive project operations should make ancestor resolution unmistakable before applying changes.