🚧 Early alpha — building the foundation. See the roadmap →
Distribution architecture research
The question
Section titled “The question”How does the same core logic live in an Obsidian plugin, a CLI tool, and potentially headless/CI environments?
Key findings
Section titled “Key findings”Obsidian API boundary
Section titled “Obsidian API boundary”Analyzed every source file. ~50-60% of Crosswalker is pure logic with no Obsidian dependency:
| File | Obsidian dependency | Extractable |
|---|---|---|
| config-manager.ts | No | Yes |
| csv-parser.ts | No | Yes |
| settings-data.ts | No | Yes |
| types/config.ts | No | Yes |
| generation-engine.ts (note building) | Partial | Mostly |
| generation-engine.ts (file I/O) | Yes | Need adapter |
| main.ts | Yes | Plugin only |
| import-wizard.ts | Yes | Plugin only |
| settings-tab.ts | Yes | Plugin only |
| config-browser-modal.ts | Yes | Plugin only |
| debug.ts | Yes | Need adapter |
No vault API for CLI
Section titled “No vault API for CLI”- The
obsidiannpm package is plugin-scoped only — can’t useapp.vaultfrom Node.js - obsidian-headless exists but is sync-focused only, not a general-purpose vault API
- CLI must use Node.js
fsdirectly to read/write vault files - This is fine — Obsidian vaults ARE just folders of markdown files
The VaultAdapter pattern
Section titled “The VaultAdapter pattern”The key abstraction that makes everything work:
Core logic takes a VaultAdapter — doesn’t care if it’s Obsidian or filesystem.
Recommended structure: pnpm monorepo
Section titled “Recommended structure: pnpm monorepo”Proven pattern from VS Code extension monorepos. Prior art.
Distribution paths
Section titled “Distribution paths”| Package | Distribution | Users |
|---|---|---|
@crosswalker/core | npm (internal) | Other packages |
| Obsidian plugin | GitHub Releases + Obsidian registry | End users |
@crosswalker/cli | npm global install | Power users, CI/CD |
| Web UI (future) | Docker / self-hosted | Teams |
Constraints discovered
Section titled “Constraints discovered”- Obsidian plugins run in browser context (Electron renderer) — can’t assume Node.js APIs in plugin code
- Plugin distribution goes through Obsidian community registry, not npm
- esbuild marks
obsidianas external — it’s injected by the app at runtime - No way to make a plugin also export a library — they’re compiled single-file bundles
Decision: when to restructure
Section titled “Decision: when to restructure”This is a Foundation phase item. The monorepo restructure should happen AFTER the spec work (EvolutionPattern, FrameworkConfig v2, metadata v2) because:
- The spec defines what core functions exist
- The VaultAdapter interface depends on what operations the generation engine needs
- Restructuring before the spec means restructuring twice
Sequence: spec → restructure to monorepo → implement features against clean architecture.
Related
Section titled “Related”- Layered architecture vision — spec → library → integrations
- Why Obsidian, why files — filesystem-first design
- Vision alignment: CLI + plugin
- Ontology lifecycle — what the core library implements
- Roadmap: Foundation phase