# KarpathyWiki Obsidian Plugin Inspection **Date:** 2026-07-09 **Plugin:** `karpathywiki` / `green-dalii/obsidian-llm-wiki` **Repo inspected:** `https://github.com/green-dalii/obsidian-llm-wiki` **Fresh clone verification:** commit `0979d50` **License:** Apache-2.0 **Version observed:** 1.24.0 ## Why inspected Jason observed that the Obsidian Karpathy LLM Wiki plugin is doing much of what the Redmine ticket decomposition process should do: entity/concept extraction, knowledge graph page generation, links, indexes, and conversational query. The question was whether we can trigger it headlessly/CLI or mirror its logic. ## Repository / structure findings The plugin is a compact TypeScript Obsidian plugin. Important files: ```text src/main.ts src/wiki/wiki-engine.ts src/wiki/source-analyzer.ts src/wiki/page-factory.ts src/wiki/prompts/ingestion.ts src/wiki/prompts/generation.ts src/wiki/prompts/merge.ts src/wiki/prompts/lint.ts src/wiki/query-engine/ src/core/ ``` Package metadata: ```json { "name": "karpathywiki", "version": "1.24.0", "main": "main.js" } ``` Fresh clone verification confirmed `package.json` has no `bin` entry: ```text PACKAGE {'name': 'karpathywiki', 'version': '1.24.0', 'main': 'main.js', 'bin': None, 'license': 'Apache-2.0'} ``` There is no package `bin` entry and no obvious standalone CLI exposed by the project. ## Obsidian command entry points `src/main.ts` registers Obsidian commands: ```text ingest-source ingest-folder ingest-multiple-files query-wiki lint-wiki regenerate-index cancel-ingestion ingest-active-file view-ingestion-history recreate-welcome-note ``` These are Obsidian command palette commands, not shell commands. If Obsidian is running, it may be possible to trigger commands through Obsidian/Advanced URI style automation, but that would still depend on Obsidian being open and the plugin being loaded. It is not a true headless pipeline. ## Core engine dependency The core class is `WikiEngine` in `src/wiki/wiki-engine.ts`. It is separate from the plugin UI, but its constructor requires Obsidian types and APIs: ```ts constructor( app: App, settings: LLMWikiSettings, getLLMClient: () => LLMClient | null, schemaManager: SchemaManager, onFileWrite?: (path: string) => void, onProgress?: (message: string) => void, onDone?: (report: IngestReport) => void ) ``` It uses: - `app.vault.read` - `app.vault.getMarkdownFiles` - `app.vault.process` - `app.vault.create` - `app.vault.getAbstractFileByPath` - `app.metadataCache.getFileCache` - `TFile`, `TFolder`, `Notice`, `normalizePath` Therefore, the engine cannot be called directly from Node/Python CLI without either: 1. running inside Obsidian, or 2. writing an adapter/shim that emulates enough of Obsidian's `App/Vault/metadataCache/TFile` behavior. ## Portable logic worth mirroring The useful logic is not locked to Obsidian conceptually. It can be mirrored or adapted: ### Source analysis `src/wiki/source-analyzer.ts`: - reads source content - checks blank/duplicate content - prompts LLM for structured JSON - extracts entities and concepts - includes aliases - collects verbatim quotes / provenance - identifies contradictions, related pages, key points - normalizes irregular LLM JSON The core ingestion prompt is in `src/wiki/prompts/ingestion.ts`. Notable extraction output shape: ```json { "source_title": "...", "summary": "...", "entities": [ { "name": "...", "type": "person|organization|project|product|event|place|other", "aliases": [], "summary": "...", "mentions_in_source": [], "mentions_with_provenance": [], "related_entities": [], "related_concepts": [] } ], "concepts": [], "contradictions": [], "related_pages": [], "key_points": [] } ``` ### Page generation `src/wiki/page-factory.ts`: - slugifies entities/concepts - checks existing pages - resolves duplicates via slug/alias/LLM semantic match - generates entity/concept pages - merges into existing pages - protects reviewed pages - corrects polluted wikilinks - injects provenance/mentions ### Prompts `src/wiki/prompts/generation.ts` includes high-value generation prompts for: - entity pages - concept pages - source summary pages - preserving reviewed pages ### Query / graph retrieval The README claims zero-embedding graph retrieval via Personalized PageRank over the wiki link graph. Source references in `WikiEngine` show: ```ts buildGraphFromContent(...) getOrBuildGraph(...) ``` and query pipeline files exist under: ```text src/wiki/query-engine/pipeline/ ``` This is useful design inspiration, but not required for the first Redmine decomposition tool because gbrain already supplies search/indexing and the vault graph itself supplies wikilinks. ## Recommendation Do **not** depend on Obsidian running for Redmine ticket decomposition. Instead: 1. Mirror the plugin's source-analysis and page-generation logic in our own CLI-oriented tool. 2. Reuse its prompt structure and output schema ideas. 3. Write directly to the filesystem vault, but outside the plugin-owned `wiki/` tree by default. 4. Use gbrain for indexing/search after files are written. 5. Keep Redmine contact updates as a separate explicit apply phase. 6. Preserve compatibility with Obsidian/KarpathyWiki by using normal Markdown, wikilinks, and frontmatter fields the plugin understands where practical. Compatibility rule: the plugin owns `wiki/entities`, `wiki/concepts`, `wiki/sources`, `wiki/index.md`, and `wiki/log.md`. The headless decomposer should default to LDR-owned paths like `Timeline/`, `entities/organizations/`, and `Processes/Redmine/`, linking to `wiki/...` pages when useful but not editing them. This gives us the same broad effect without requiring a GUI Obsidian session and without competing with the existing plugin state. ## Possible implementation paths ### Path A — Thin TypeScript headless port Build a Node/TypeScript CLI in `/home/jason/projects/redmine` or a sibling project that imports/copied logic from the plugin and supplies a fake Obsidian adapter. Pros: - Closer to upstream code. - Easier to vendor future prompt improvements. - Can reuse zod/AI SDK provider setup. Cons: - Need to emulate enough of Obsidian `Vault`, `TFile`, metadata cache, and settings. - Adds Node/TypeScript toolchain complexity to Redmine workflow. ### Path B — Python mirror using existing Redmine tooling Implement the same conceptual pipeline in Python alongside `redmine_tickets.py`: - source normalization - LLM JSON extraction - entity/concept dedup via filesystem search + slug rules - page generation templates - timeline/entity writers - gbrain sync hooks Pros: - Fits current Redmine tooling. - Easier to integrate with ticket cache and contact updates. - No Obsidian runtime needed. Cons: - We do not directly reuse TypeScript implementation. - Need to maintain our own prompt/schema logic. ### Path C — Obsidian-driven automation Use Obsidian command automation / Advanced URI to trigger plugin commands. Pros: - Minimal code if it works. Cons: - Requires Obsidian running. - Harder to make deterministic/headless/cron-safe. - Harder to feed Redmine tickets and capture structured contact-update proposals. ## Best fit for LDR Redmine decomposition Path B is the best first implementation path. Reasons: - Redmine tickets are already fetched/cached in Python. - We need Redmine contact updates and safety gates. - We need Onyx URLs and gbrain sync hooks. - We need headless/cron/agent execution. - We already proved manual note generation format in the decomposition pilot. Use the plugin as a reference for: - `src/wiki/prompts/ingestion.ts` — source analysis prompt and entity/concept output shape - `src/wiki/prompts/generation.ts` — entity/concept/source page generation prompts - `src/wiki/prompts/merge.ts` — classify-then-route merge strategy for updating existing pages - `src/wiki/prompts/lint.ts` — wiki quality checks and contradiction review ideas - `src/wiki/source-analyzer.ts` — JSON normalization, duplicate/blank source handling, provenance mentions - `src/wiki/page-factory.ts` — slug/alias resolution, cross-type collision handling, merge-vs-append routing - `src/wiki/query-engine/` — graph retrieval ideas for later, not first pass Do not try to invoke it via Obsidian as the primary production pipeline; use the source as a design reference for a headless Python mirror. ## Immediate next action Update `ticket_decomposition_knowledge_ingestion_plan.md` so Phase 2 says: - use KarpathyWiki plugin prompt/schema as reference - implement a Python headless mirror first - consider TypeScript adapter later only if Python mirror becomes too costly Then implement a `decompose --dry-run` engine using the pilot tickets as fixtures.