Files
redmine/docs/karpathywiki_plugin_inspection.md
T
Jason Thistlethwaite 9ee9eb3ec6 Organized
2026-10-17 20:50:35 -04:00

8.6 KiB

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:

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:

{
  "name": "karpathywiki",
  "version": "1.24.0",
  "main": "main.js"
}

Fresh clone verification confirmed package.json has no bin entry:

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:

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:

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:

{
  "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:

buildGraphFromContent(...)
getOrBuildGraph(...)

and query pipeline files exist under:

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.