From pkos
Scans ~/Code/Projects/*/docs/ for crystals, lessons, and design docs, imports to PKOS vault with Obsidian Flavored Markdown. Use when the user says 'harvest', 'scan projects', 'import knowledge', or via Adam cron.
npx claudepluginhub n0rvyn/indie-toolkit --plugin pkosThis skill uses the workspace's default tool permissions.
Scans all projects under `~/Code/Projects/` for high-value knowledge documents (crystals, lessons, design docs) and imports them into the PKOS vault at `~/Obsidian/PKOS/30-Projects/{project}/`. Uses incremental hash-based change detection to only process new or modified files. After import, dispatches ripple-compiler for each note to build cross-project MOC linkage.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
Retrieves current documentation, API references, and code examples for libraries, frameworks, SDKs, CLIs, and services via Context7 CLI. Ideal for API syntax, configs, migrations, and setup queries.
Uses ctx7 CLI to fetch current library docs, manage AI coding skills (install/search/generate), and configure Context7 MCP for AI editors.
Scans all projects under ~/Code/Projects/ for high-value knowledge documents (crystals, lessons, design docs) and imports them into the PKOS vault at ~/Obsidian/PKOS/30-Projects/{project}/. Uses incremental hash-based change detection to only process new or modified files. After import, dispatches ripple-compiler for each note to build cross-project MOC linkage.
Harvest scope (per crystal D-S01, D-S02):
docs/11-crystals/*-crystal.md — decision recordsdocs/09-lessons-learned/*.md OR docs/09-lessons/*.md — lessons learneddocs/06-plans/*-design.md — design documents (NOT plans, NOT dev-guides)--dry-run: Show what would be imported without writing files--force: Re-import all files even if hash unchanged--project NAME: Only harvest from a specific project (default: all)--skip-ripple: Skip ripple compilation after import (faster, for bulk initial import)find ~/Code/Projects -maxdepth 1 -type d ! -name ".*" ! -name "Z-Archived" | sort
For each project directory, check if docs/ exists:
test -d ~/Code/Projects/{project}/docs && echo "has docs"
Skip projects without a docs/ directory.
If --project NAME specified, filter to only that project.
Read ~/Obsidian/PKOS/.state/harvest-state.yaml:
harvested:
- source: "Adam/docs/11-crystals/2026-03-18-goal-driven-architecture-crystal.md"
hash: "a1b2c3d4..."
vault_path: "30-Projects/Adam/goal-driven-architecture-crystal.md"
type: crystal
date: "2026-04-08"
- source: "Runetic/docs/09-lessons-learned/first-attempt-failure.md"
hash: "e5f6g7h8..."
vault_path: "30-Projects/Runetic/first-attempt-failure.md"
type: lesson
date: "2026-04-08"
last_harvest: "2026-04-08T10:00:00"
If file does not exist, initialize with empty list.
For each project with docs/:
Crystals:
find ~/Code/Projects/{project}/docs/11-crystals -name "*-crystal.md" 2>/dev/null
Lessons:
find ~/Code/Projects/{project}/docs/09-lessons* -name "*.md" 2>/dev/null
Design docs:
find ~/Code/Projects/{project}/docs/06-plans -name "*-design.md" 2>/dev/null
For each found file:
md5 -q "{file_path}"If --force: treat all files as new regardless of hash.
Collect candidates. Present summary:
Harvest scan: {N} projects, {M} documents found
New: {new_count} (crystals: {c}, lessons: {l}, designs: {d})
Updated: {updated_count}
Unchanged: {unchanged_count}
If --dry-run: display the full list and stop.
For each candidate (new or updated):
Read the full file content. Extract frontmatter if present (YAML between --- markers).
| Source pattern | Type | PKOS type value |
|---|---|---|
11-crystals/*-crystal.md | crystal | reference |
09-lessons*/*.md | lesson | knowledge |
06-plans/*-design.md | design | reference |
If frontmatter exists:
tags: (or tags: / keywords: — normalize to tags:)date: or infer from filename (YYYY-MM-DD- prefix)status: if presentIf no frontmatter (older projects like ModelProxy):
# headingactive (crystals) or seed (lessons/designs)Generate the vault note following references/obsidian-format.md:
---
type: {PKOS type from 4b}
source: project-harvest
created: {date}
tags: [{extracted or inferred tags}]
quality: 1
citations: 0
related: []
status: {extracted or "seed"}
harvest_source: "{project}/{relative_path}"
harvest_project: "{project}"
harvest_type: "{crystal|lesson|design}"
aliases: []
---
# {title}
> [!insight] Project: {project}
> Harvested from `{project}/docs/{relative_path}` on {today's date}.
> Type: {crystal|lesson|design doc}
{body content — preserve original markdown}
## Connections
{Scan PKOS vault for tag-overlapping notes in 30-Projects/ and 10-Knowledge/:}
{For each match: `- [[{note-title}]]`}
{If a MOC exists for any of this note's tags: `- See also: [[MOC-{tag}]]`}
Format rules:
[[references]]), preserve themdocs/06-plans/... → just the filename)Target: ~/Obsidian/PKOS/30-Projects/{project}/{filename}
mkdir -p ~/Obsidian/PKOS/30-Projects/{project}
Use the source filename as the vault filename. If a file with the same name already exists from a different source path (collision), append the source directory as suffix: {filename-without-ext}-{dir-slug}.md.
Write the converted note using the Write tool.
Add or update the entry in the harvested list with new hash and vault_path.
Skip this step if --skip-ripple.
For each newly imported or updated note, dispatch pkos:ripple-compiler agent with:
note_path: "30-Projects/{project}/{filename}"
title: "{title}"
tags: [{tags from frontmatter}]
related_notes: [{related notes from Connections section}]
Dispatch sequentially (not parallel) to avoid concurrent MOC edits.
If ripple fails for a note, log warning and continue — the source note is already saved.
Write updated ~/Obsidian/PKOS/.state/harvest-state.yaml with all entries (existing unchanged + new + updated).
PKOS Harvest — {date}
Projects scanned: {N}
Documents found: {M}
Imported: {K} (new: {new}, updated: {upd})
Skipped: {S} (unchanged: {unch}, errors: {err})
By type: crystals={c}, lessons={l}, designs={d}
By project: {top 5 projects by import count}
Ripple compilation:
MOCs updated: {count}
MOCs created: {count}
Cross-references added: {count}
Run /generate-bases-views --target cross-project to update Bases views.
.state/harvest-state.yaml.bak, reinitialize