Initial commit
This commit is contained in:
240
skills/obsidian-vault-manager/README.md
Normal file
240
skills/obsidian-vault-manager/README.md
Normal file
@@ -0,0 +1,240 @@
|
||||
# Obsidian Vault Manager Plugin
|
||||
|
||||
Manage an AI-powered Obsidian knowledge base with automatic organization and GitHub Pages publishing.
|
||||
|
||||
## Features
|
||||
|
||||
- **YouTube Video Capture**: Fetch transcripts and create comprehensive notes (`/youtube-note`)
|
||||
- **Smart AI Tagging**: Automatic tagging based on content analysis (`/capture`, `/idea`)
|
||||
- **Bundled Scripts**: Executable scripts for transcript fetching and publishing
|
||||
- **Template System**: Consistent note structure across all content types
|
||||
- **GitHub Pages Publishing**: Publish notes to your public sharehub (`/publish`)
|
||||
|
||||
## Installation
|
||||
|
||||
### Claude Code CLI (Recommended)
|
||||
|
||||
1. **Add the plugin marketplace**:
|
||||
```bash
|
||||
/plugin marketplace add ZorroCheng-MC/obsidian-vault-manager-plugin
|
||||
```
|
||||
|
||||
2. **Install the plugin**:
|
||||
```bash
|
||||
# Option A: Browse available plugins
|
||||
/plugin
|
||||
|
||||
# Option B: Install directly
|
||||
/plugin install obsidian-vault-manager@ZorroCheng-MC/obsidian-vault-manager-plugin
|
||||
```
|
||||
|
||||
3. **Verify installation**:
|
||||
```bash
|
||||
/plugin list
|
||||
# Should show: obsidian-vault-manager
|
||||
```
|
||||
|
||||
### Manual Installation (Legacy)
|
||||
|
||||
For development or when marketplace is unavailable:
|
||||
|
||||
```bash
|
||||
# Clone to Claude plugins directory
|
||||
mkdir -p ~/.claude/plugins
|
||||
cd ~/.claude/plugins
|
||||
git clone https://github.com/ZorroCheng-MC/obsidian-vault-manager-plugin.git obsidian-vault-manager
|
||||
|
||||
# Make scripts executable
|
||||
chmod +x ~/.claude/plugins/obsidian-vault-manager/scripts/core/*.sh
|
||||
```
|
||||
|
||||
## Bundled Resources
|
||||
|
||||
### Scripts
|
||||
|
||||
**Core Scripts (`scripts/core/`)**:
|
||||
- `fetch-youtube-transcript.sh` - Fetches YouTube transcripts using youtube_transcript_api
|
||||
|
||||
**Validation Scripts (`scripts/validation/`)**:
|
||||
- `validate-frontmatter.py` - Validates note frontmatter structure
|
||||
|
||||
### Templates
|
||||
|
||||
**`templates/youtube-note-template.md`** - Structured template for YouTube video notes with:
|
||||
- Comprehensive frontmatter
|
||||
- Learning objectives
|
||||
- Curriculum structure
|
||||
- Key takeaways sections
|
||||
- Rating and tags analysis
|
||||
|
||||
## Usage
|
||||
|
||||
### In Claude Code CLI
|
||||
|
||||
```bash
|
||||
/youtube-note https://youtu.be/VIDEO_ID
|
||||
```
|
||||
|
||||
### In Claude Desktop
|
||||
|
||||
Simply provide a YouTube URL:
|
||||
```
|
||||
Create a note from this video: https://youtu.be/VIDEO_ID
|
||||
```
|
||||
|
||||
## Optional: Automatic Validation Hooks
|
||||
|
||||
For advanced users who want automatic frontmatter validation before note creation, you can configure hooks in your Claude Code settings.
|
||||
|
||||
### Hook Setup
|
||||
|
||||
Add the following to your `~/.claude/settings.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"PreToolUse": [
|
||||
{
|
||||
"description": "Validate frontmatter before creating Obsidian notes",
|
||||
"matcher": "mcp__obsidian-mcp-tools__create_vault_file",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "python3 ~/.claude/skills/obsidian-vault-manager/scripts/validation/validate-frontmatter.py"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### What Hooks Do
|
||||
|
||||
When configured, the validation hook will:
|
||||
- ✅ Run automatically before every note creation
|
||||
- ✅ Check for required frontmatter fields (title, tags, date, type)
|
||||
- ✅ Validate tag structure (must be a list)
|
||||
- ✅ Verify content type tag is present (video, article, idea, etc.)
|
||||
- ✅ Warn if 'inbox' tag is missing
|
||||
- ❌ Block creation if validation fails
|
||||
|
||||
### Hook Behavior
|
||||
|
||||
**Exit Codes**:
|
||||
- `0` - Validation passed, allow creation
|
||||
- `1` - Warning only, allow creation with message
|
||||
- `2` - Validation failed, block creation
|
||||
|
||||
**Without Hooks**: Claude runs validation script as part of SKILL.md workflow (default behavior)
|
||||
|
||||
**With Hooks**: Automatic enforcement before any Obsidian note creation (opt-in)
|
||||
|
||||
## Testing Scripts
|
||||
|
||||
### Test Transcript Fetching
|
||||
|
||||
```bash
|
||||
# Test with a video ID
|
||||
~/.claude/skills/obsidian-vault-manager/scripts/core/fetch-youtube-transcript.sh jI2LC3WTryw
|
||||
```
|
||||
|
||||
### Test Validation
|
||||
|
||||
```bash
|
||||
# Create a test file
|
||||
cat > test-note.md << 'EOF'
|
||||
---
|
||||
title: "Test Video"
|
||||
tags: [video, AI, inbox]
|
||||
date: 2025-10-28
|
||||
type: video
|
||||
---
|
||||
# Test
|
||||
EOF
|
||||
|
||||
# Validate it
|
||||
python3 ~/.claude/skills/obsidian-vault-manager/scripts/validation/validate-frontmatter.py test-note.md
|
||||
```
|
||||
|
||||
## Tag Taxonomy
|
||||
|
||||
### Content Type Tags (choose 1)
|
||||
- `idea`, `video`, `article`, `study-guide`, `repository`, `reference`, `project`
|
||||
|
||||
### Topic Tags (choose 2-4)
|
||||
- `AI`, `productivity`, `knowledge-management`, `development`, `learning`, `research`, `writing`, `tools`, `business`, `design`, `automation`, `data-science`, `web-development`, `personal-growth`, `finance`
|
||||
|
||||
### Status Tags (choose 1)
|
||||
- `inbox`, `processing`, `evergreen`, `published`, `archived`, `needs-review`
|
||||
|
||||
### Metadata Tags (choose 0-2)
|
||||
- `high-priority`, `quick-read`, `deep-dive`, `technical`, `conceptual`, `actionable`, `tutorial`, `inspiration`
|
||||
|
||||
**Total tags**: 6-8 for optimal filtering
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Script Permission Errors
|
||||
|
||||
Make scripts executable:
|
||||
```bash
|
||||
chmod +x ~/.claude/skills/obsidian-vault-manager/scripts/core/*.sh
|
||||
chmod +x ~/.claude/skills/obsidian-vault-manager/scripts/validation/*.py
|
||||
```
|
||||
|
||||
### Transcript Fetching Fails
|
||||
|
||||
Ensure `uvx` and `youtube_transcript_api` are available:
|
||||
```bash
|
||||
uvx youtube_transcript_api --help
|
||||
```
|
||||
|
||||
### Validation Errors
|
||||
|
||||
Check Python dependencies:
|
||||
```bash
|
||||
python3 -c "import yaml; print('PyYAML installed')"
|
||||
```
|
||||
|
||||
If missing:
|
||||
```bash
|
||||
pip3 install pyyaml
|
||||
```
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
~/.claude/skills/obsidian-vault-manager/
|
||||
├── SKILL.md # Main skill file with instructions
|
||||
├── README.md # This file
|
||||
├── scripts/
|
||||
│ ├── core/
|
||||
│ │ └── fetch-youtube-transcript.sh
|
||||
│ └── validation/
|
||||
│ └── validate-frontmatter.py
|
||||
└── templates/
|
||||
└── youtube-note-template.md
|
||||
```
|
||||
|
||||
## Version
|
||||
|
||||
- **Version**: 1.0.0 (Post-Migration)
|
||||
- **Migration Date**: 2025-10-28
|
||||
- **Architecture**: Skill-primary with bundled scripts
|
||||
|
||||
## License
|
||||
|
||||
This skill is provided for personal use. Modify and distribute as needed.
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions:
|
||||
1. Check this README
|
||||
2. Verify script permissions
|
||||
3. Test scripts individually
|
||||
4. Review SKILL.md for workflow details
|
||||
|
||||
---
|
||||
|
||||
**Note**: Hooks are optional. The skill works without hook configuration - Claude will run validation scripts as part of the workflow instructions in SKILL.md.
|
||||
611
skills/obsidian-vault-manager/SKILL.md
Normal file
611
skills/obsidian-vault-manager/SKILL.md
Normal file
@@ -0,0 +1,611 @@
|
||||
---
|
||||
name: obsidian-vault-manager
|
||||
description: Manage Obsidian knowledge base - capture ideas, YouTube videos, articles, repositories, create study guides, and publish to GitHub Pages. Use smart AI tagging for automatic organization.
|
||||
allowed-tools:
|
||||
- mcp__obsidian-mcp-tools__*
|
||||
- mcp__MCP_DOCKER__create_or_update_file
|
||||
- mcp__MCP_DOCKER__push_files
|
||||
- mcp__MCP_DOCKER__get_file_contents
|
||||
- mcp__MCP_DOCKER__fetch
|
||||
- mcp__MCP_DOCKER__gitingest-analyze
|
||||
- Bash(uvx youtube_transcript_api:*)
|
||||
---
|
||||
|
||||
# Obsidian Vault Manager
|
||||
|
||||
Manage an AI-powered Obsidian knowledge base with automatic organization and GitHub Pages publishing.
|
||||
|
||||
## Vault Configuration
|
||||
|
||||
- **Vault Path**: `/Users/zorro/Documents/Obsidian/Claudecode`
|
||||
- **Publishing Folder**: `documents/` (auto-deploys to GitHub Pages)
|
||||
- **GitHub Repository**: `ZorroCheng-MC/sharehub`
|
||||
|
||||
## Tag Taxonomy (STRICT - Use Only These)
|
||||
|
||||
### Content Type Tags (choose 1)
|
||||
- `idea` - Random thoughts, concepts, brainstorms
|
||||
- `video` - YouTube videos, lectures
|
||||
- `article` - Web articles, blog posts
|
||||
- `study-guide` - Learning materials, courses
|
||||
- `repository` - Code repositories, technical analysis
|
||||
- `reference` - Documentation, quick lookups
|
||||
- `project` - Project notes, planning
|
||||
|
||||
### Topic Tags (choose 2-4 relevant)
|
||||
- `AI` - Artificial intelligence, machine learning
|
||||
- `productivity` - Time management, workflows, GTD
|
||||
- `knowledge-management` - PKM, note-taking, Obsidian
|
||||
- `development` - Programming, software engineering
|
||||
- `learning` - Education, study techniques
|
||||
- `research` - Academic, scientific papers
|
||||
- `writing` - Content creation, blogging
|
||||
- `tools` - Software tools, applications
|
||||
- `business` - Entrepreneurship, strategy
|
||||
- `design` - UI/UX, visual design
|
||||
- `automation` - Workflows, scripts, efficiency
|
||||
- `data-science` - Analytics, statistics
|
||||
- `web-development` - Frontend, backend, full-stack
|
||||
- `personal-growth` - Self-improvement, habits
|
||||
- `finance` - Money, investing, economics
|
||||
|
||||
### Status Tags (choose 1)
|
||||
- `inbox` - Just captured, needs processing
|
||||
- `processing` - Currently working on
|
||||
- `evergreen` - Timeless, permanent knowledge
|
||||
- `published` - Shared publicly
|
||||
- `archived` - Done, historical reference
|
||||
- `needs-review` - Requires attention
|
||||
|
||||
### Priority/Metadata Tags (choose 0-2)
|
||||
- `high-priority` - Important, urgent
|
||||
- `quick-read` - <5 min to consume
|
||||
- `deep-dive` - Complex, requires focus
|
||||
- `technical` - Code-heavy, engineering
|
||||
- `conceptual` - Theory, ideas, frameworks
|
||||
- `actionable` - Contains next steps/todos
|
||||
- `tutorial` - Step-by-step guide
|
||||
- `inspiration` - Creative, motivational
|
||||
|
||||
## Core Operations
|
||||
|
||||
### 1. Capture Content (Universal Inbox)
|
||||
|
||||
Intelligently route content based on type and create properly tagged notes.
|
||||
|
||||
#### YouTube Videos
|
||||
|
||||
**Bundled Resources:**
|
||||
- **Script**: `scripts/core/fetch-youtube-transcript.sh` - Fetches transcript via uvx
|
||||
- **Template**: `templates/youtube-note-template.md` - Note structure
|
||||
- **Validation**: `scripts/validation/validate-frontmatter.py` - Quality check
|
||||
|
||||
When user provides a YouTube URL:
|
||||
|
||||
**Step 1: Extract Video ID and Fetch Transcript**
|
||||
1. Extract VIDEO_ID from URL (e.g., `https://youtu.be/VIDEO_ID` or `https://www.youtube.com/watch?v=VIDEO_ID`)
|
||||
2. Run bundled script to fetch transcript:
|
||||
```bash
|
||||
SKILL_DIR="$HOME/.claude/skills/obsidian-vault-manager"
|
||||
TRANSCRIPT=$("$SKILL_DIR/scripts/core/fetch-youtube-transcript.sh" "$VIDEO_ID")
|
||||
```
|
||||
3. Use `get_transcript` to get video transcript and `fetch` to get YouTube page for metadata (title, channel, description)
|
||||
|
||||
**Step 2: Analyze Content for Smart Tags**
|
||||
Determine:
|
||||
- Main topics (choose 2-4 from taxonomy)
|
||||
- Complexity level:
|
||||
- `quick-read` = under 10 minutes
|
||||
- `tutorial` = step-by-step instructional
|
||||
- `deep-dive` = 30+ minutes, complex
|
||||
- Content characteristics:
|
||||
- `technical` = code-heavy, engineering
|
||||
- `conceptual` = theory, frameworks
|
||||
- `actionable` = practical steps
|
||||
- `inspiration` = motivational
|
||||
- Priority (high/medium/low based on relevance)
|
||||
|
||||
**Step 3: Generate Filename**
|
||||
Format: `[date]-[creator-or-channel]-[descriptive-title].md`
|
||||
Example: `2025-10-24-ai-labs-context-engineering-claude-code.md`
|
||||
|
||||
**Step 4: Load Template and Substitute Variables**
|
||||
|
||||
1. Load bundled template:
|
||||
```bash
|
||||
TEMPLATE=$(cat "$SKILL_DIR/templates/youtube-note-template.md")
|
||||
```
|
||||
|
||||
2. Substitute placeholders with analyzed data:
|
||||
- `{{TITLE}}` - Video title from metadata
|
||||
- `{{VIDEO_ID}}` - Extracted video ID
|
||||
- `{{CHANNEL}}` - Channel name
|
||||
- `{{DATE}}` - Current date (YYYY-MM-DD)
|
||||
- `{{TOPIC_TAGS}}` - 2-4 topic tags from taxonomy
|
||||
- `{{METADATA_TAGS}}` - 1-2 metadata tags (tutorial, actionable, etc.)
|
||||
- `{{PRIORITY}}` - high/medium/low
|
||||
- `{{DURATION}}` - Estimated duration (~X minutes)
|
||||
- `{{DESCRIPTION}}` - 2-3 sentence summary from transcript analysis
|
||||
- `{{LEARNING_OBJECTIVES}}` - Bullet list of learning outcomes
|
||||
- `{{CURRICULUM}}` - Structured outline with checkboxes
|
||||
- `{{MAIN_INSIGHTS}}` - 3-5 key insights from transcript
|
||||
- `{{ACTIONABLE_POINTS}}` - Practical takeaways
|
||||
- `{{TARGET_AUDIENCE}}` - Who should watch this
|
||||
- `{{TOPIC_ANALYSIS}}` - Explanation of chosen topics
|
||||
- `{{COMPLEXITY_LEVEL}}` - quick-read/tutorial/deep-dive
|
||||
- `{{PRIORITY_REASONING}}` - Why this priority
|
||||
- `{{TAG_REASONING}}` - Tag selection explanation
|
||||
- `{{PRIMARY_TOPIC}}` - Main topic for filtering
|
||||
- `{{RELATED_SEARCHES}}` - Suggested semantic searches
|
||||
- `{{CONNECTIONS}}` - Links to related notes
|
||||
|
||||
**Step 5: Create Enhanced Video Entry**
|
||||
|
||||
Use `mcp__obsidian-mcp-tools__create_vault_file` with the substituted template content.
|
||||
|
||||
**Tag Count:** 6-8 tags total
|
||||
**Always include:** `video`, `inbox`, 2-4 topic tags, 1-2 metadata tags, optional content-specific tags
|
||||
|
||||
#### Ideas & Quick Thoughts
|
||||
|
||||
**Bundled Resources:**
|
||||
- **Template**: `templates/idea-template.md` - Idea note structure
|
||||
|
||||
When user provides plain text (no URL):
|
||||
|
||||
**Step 1: Analyze the Idea**
|
||||
Extract:
|
||||
1. Main concept (for title)
|
||||
2. Related topics (choose 2-4 from taxonomy)
|
||||
3. Idea type:
|
||||
- `actionable` = has concrete next steps
|
||||
- `conceptual` = theoretical, framework-based
|
||||
- `inspiration` = creative, motivational
|
||||
- `high-priority` = urgent or important
|
||||
4. Brief description (1-2 sentences explaining the idea clearly)
|
||||
|
||||
**Step 2: Generate Smart Filename**
|
||||
Format: `{date}-{3-5-word-idea-name}.md`
|
||||
|
||||
Examples:
|
||||
- "Use AI to automatically categorize notes" → `2025-10-23-ai-note-categorization.md`
|
||||
- "Knowledge compounds when connected" → `2025-10-23-knowledge-compound-connections.md`
|
||||
|
||||
**Step 3: Load Template and Substitute Variables**
|
||||
|
||||
1. Load bundled template:
|
||||
```bash
|
||||
SKILL_DIR="$HOME/.claude/skills/obsidian-vault-manager"
|
||||
TEMPLATE=$(cat "$SKILL_DIR/templates/idea-template.md")
|
||||
```
|
||||
|
||||
2. Substitute placeholders with analyzed data:
|
||||
- `{{TITLE}}` - Concise idea title
|
||||
- `{{TOPIC_TAGS}}` - 2-4 topic tags from taxonomy (comma-separated)
|
||||
- `{{METADATA_TAGS}}` - 1-2 metadata tags (actionable, conceptual, inspiration, etc.)
|
||||
- `{{DATE}}` - Current date (YYYY-MM-DD)
|
||||
- `{{PRIORITY}}` - high/medium/low
|
||||
- `{{CORE_IDEA}}` - Cleaned idea description (1-2 paragraphs)
|
||||
- `{{WHY_MATTERS}}` - 1-2 sentences on potential impact or value
|
||||
- `{{RELATED_CONCEPTS}}` - Bullet list of related concepts
|
||||
- `{{NEXT_STEPS}}` - If actionable: 2-3 next steps. Otherwise: "Further research needed"
|
||||
- `{{TOPICS_EXPLANATION}}` - Explanation of why these topics were chosen
|
||||
- `{{CHARACTERISTICS_EXPLANATION}}` - Why it's actionable/conceptual/inspiration
|
||||
- `{{PRIORITY_EXPLANATION}}` - Reasoning for priority level
|
||||
- `{{TAG_REASONING}}` - Overall tag selection explanation
|
||||
- `{{PRIMARY_TOPIC}}` - Main topic for filtering
|
||||
- `{{SECONDARY_TOPIC}}` - Secondary topic for filtering
|
||||
- `{{RELATED_CONCEPT}}` - For semantic search suggestions
|
||||
|
||||
**Step 4: Create Enhanced Idea File**
|
||||
|
||||
Use `mcp__obsidian-mcp-tools__create_vault_file` with the substituted template content.
|
||||
|
||||
**Tag Count:** 5-8 tags total
|
||||
**Always include:** `idea`, `inbox`, 2-4 topic tags, 1-2 metadata tags
|
||||
|
||||
#### GitHub Repositories
|
||||
|
||||
When user provides a GitHub URL:
|
||||
|
||||
**Step 1: Analyze Repository**
|
||||
Use `gitingest-analyze` with:
|
||||
- `source`: GitHub URL
|
||||
- `include_patterns`: `["*.md", "*.py", "*.js", "*.ts"]` (adapt to repo language)
|
||||
- `max_file_size`: 10485760 (10MB)
|
||||
|
||||
**Step 2: Create Repository Analysis Note**
|
||||
|
||||
Use `mcp__obsidian-mcp-tools__create_vault_file`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: "[Repo Name] - Repository Analysis"
|
||||
tags: [repository, {language}, {topic}, inbox, technical, reference]
|
||||
url: [github_url]
|
||||
date: YYYY-MM-DD
|
||||
type: repository
|
||||
status: inbox
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## 📦 Repository Overview
|
||||
[Repository description from README]
|
||||
|
||||
## 🏗️ Architecture
|
||||
[Key components and structure from gitingest analysis]
|
||||
|
||||
## 📁 Key Files & Components
|
||||
[Important files identified in analysis]
|
||||
|
||||
## 📝 Documentation Summary
|
||||
[Main docs and README content]
|
||||
|
||||
## 💡 Key Patterns & Insights
|
||||
[Notable patterns, technologies, approaches]
|
||||
|
||||
## 🏷️ Tags Analysis
|
||||
- **Topics:** {why these topics}
|
||||
- **Language:** {primary programming language}
|
||||
- **Bases Filtering:** `type = repository AND tags contains "{topic}"`
|
||||
|
||||
---
|
||||
*Captured: {date}*
|
||||
*Source: {repo_url}*
|
||||
```
|
||||
|
||||
**Tag Count:** 6-8 tags
|
||||
|
||||
#### Web Articles
|
||||
|
||||
When user provides web article URL:
|
||||
|
||||
**Step 1: Fetch Content**
|
||||
Use `mcp__MCP_DOCKER__fetch` to get article content
|
||||
|
||||
**Step 2: Create Article Note**
|
||||
|
||||
Use `mcp__obsidian-mcp-tools__create_vault_file`:
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: "[Article Title]"
|
||||
tags: [article, {topic1}, {topic2}, {topic3}, inbox, quick-read]
|
||||
url: [article_url]
|
||||
date: YYYY-MM-DD
|
||||
type: article
|
||||
status: inbox
|
||||
priority: medium
|
||||
---
|
||||
|
||||
## 📄 Summary
|
||||
[AI-generated summary of key points]
|
||||
|
||||
## 🔑 Key Takeaways
|
||||
- [Point 1]
|
||||
- [Point 2]
|
||||
- [Point 3]
|
||||
|
||||
## 💭 Personal Notes
|
||||
[Space for user's thoughts]
|
||||
|
||||
## 🔗 Related Resources
|
||||
[Links mentioned in article]
|
||||
|
||||
## 🏷️ Tags Analysis
|
||||
- **Topics:** {explanation}
|
||||
- **Bases Filtering:** `type = article AND tags contains "{topic}"`
|
||||
|
||||
---
|
||||
*Captured: {date}*
|
||||
```
|
||||
|
||||
**Tag Count:** 6-8 tags
|
||||
|
||||
### 2. Create Study Guides
|
||||
|
||||
**Bundled Resources:**
|
||||
- **Template**: `templates/study-guide-template.md` - Study guide structure
|
||||
|
||||
When user requests study guide from URL or content:
|
||||
|
||||
**Step 1: Fetch Content**
|
||||
- If URL: use `mcp__MCP_DOCKER__fetch`
|
||||
- If file: use `mcp__obsidian-mcp-tools__get_vault_file`
|
||||
- If direct text: use provided content
|
||||
|
||||
**Step 2: Analyze for Smart Tagging**
|
||||
Identify:
|
||||
- Main topics and themes → Choose 2-4 topic tags from taxonomy
|
||||
- Complexity level → `deep-dive` (multi-hour), `technical` (code/math), `conceptual` (theory)
|
||||
- Practical application → `actionable` (exercises) or `tutorial` (step-by-step)
|
||||
- Learning prerequisites → Determines difficulty level
|
||||
- Estimated study time → Hours required
|
||||
- Priority (high/medium/low based on goals)
|
||||
|
||||
**Step 3: Generate Filename**
|
||||
Format: `[date]-[topic-name]-study-guide.md`
|
||||
|
||||
Examples:
|
||||
- Machine learning basics → `2025-10-28-machine-learning-study-guide.md`
|
||||
- React advanced patterns → `2025-10-28-react-advanced-study-guide.md`
|
||||
|
||||
**Step 4: Load Template and Substitute Variables**
|
||||
|
||||
1. Load bundled template:
|
||||
```bash
|
||||
SKILL_DIR="$HOME/.claude/skills/obsidian-vault-manager"
|
||||
TEMPLATE=$(cat "$SKILL_DIR/templates/study-guide-template.md")
|
||||
```
|
||||
|
||||
2. Substitute placeholders with analyzed data:
|
||||
- `{{TITLE}}` - Study subject/topic name
|
||||
- `{{TOPIC_TAGS}}` - 2-4 topic tags from taxonomy (comma-separated)
|
||||
- `{{METADATA_TAGS}}` - 1-2 metadata tags (deep-dive, technical, tutorial, etc.)
|
||||
- `{{SOURCE}}` - Source URL or file reference
|
||||
- `{{DATE}}` - Current date (YYYY-MM-DD)
|
||||
- `{{DIFFICULTY}}` - beginner/intermediate/advanced
|
||||
- `{{ESTIMATED_TIME}}` - Study time (e.g., "40 hours", "2 weeks")
|
||||
- `{{PRIORITY}}` - high/medium/low
|
||||
- `{{LEARNING_OBJECTIVES}}` - Bulleted checklist of objectives
|
||||
- `{{PREREQUISITES}}` - Required background knowledge
|
||||
- `{{STUDY_METHOD}}` - Recommended approach (active reading, practice-based, mixed)
|
||||
- `{{CONTENT_STRUCTURE}}` - Weekly breakdown with concepts/activities/assessments
|
||||
- `{{MATERIAL_STRATEGIES}}` - Content-specific study strategies
|
||||
- `{{PRACTICE_EXERCISES}}` - Practical exercises or projects
|
||||
- `{{TEACHING_TECHNIQUES}}` - How to teach/explain concepts
|
||||
- `{{WEEK1_ASSESSMENT}}` - Early knowledge check questions
|
||||
- `{{FINAL_ASSESSMENT}}` - Comprehensive assessment questions
|
||||
- `{{PROGRESS_STATUS}}` - Weekly completion tracking checklist
|
||||
- `{{NEXT_MILESTONE}}` - Specific next goal
|
||||
- `{{RELATED_NOTES}}` - Wiki-style links to related content
|
||||
- `{{TOPICS_EXPLANATION}}` - Why these topics were chosen
|
||||
- `{{DIFFICULTY_EXPLANATION}}` - Difficulty level reasoning
|
||||
- `{{CHARACTERISTICS_EXPLANATION}}` - Content characteristics (technical, deep-dive, etc.)
|
||||
- `{{PRIORITY_EXPLANATION}}` - Priority reasoning
|
||||
- `{{TAG_REASONING}}` - Overall tag selection explanation
|
||||
- `{{PRIMARY_TOPIC}}` - Main topic for filtering
|
||||
- `{{SECONDARY_TOPIC}}` - Secondary topic for filtering
|
||||
- `{{RELATED_CONCEPT}}` - For semantic searches
|
||||
- `{{FOUNDATIONAL_TOPIC}}` - Base knowledge topic
|
||||
- `{{NEXT_ACTION}}` - Specific next step in study plan
|
||||
|
||||
**Step 5: Create Enhanced Study Guide**
|
||||
|
||||
Use `mcp__obsidian-mcp-tools__create_vault_file` with the substituted template content.
|
||||
|
||||
**Tag Count:** 6-8 tags total
|
||||
**Status:** Always use `processing` for study guides (not `inbox`)
|
||||
**Always include:** `study-guide`, `processing`, 2-4 topic tags, 1-2 metadata tags
|
||||
|
||||
### 3. Search Vault (Semantic Search)
|
||||
|
||||
When user asks to search vault:
|
||||
|
||||
**Use Semantic Search:**
|
||||
|
||||
Since Smart Connections is configured, use `mcp__obsidian-mcp-tools__search_vault_smart` with the query:
|
||||
|
||||
```
|
||||
mcp__obsidian-mcp-tools__search_vault_smart({
|
||||
query: "[user's search query]",
|
||||
filter: {
|
||||
limit: 5
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
**Present results showing:**
|
||||
- Note titles
|
||||
- Relevant excerpts
|
||||
- Tags and metadata
|
||||
- Connections to other notes
|
||||
|
||||
**Example queries:**
|
||||
- "Search for notes about productivity and AI"
|
||||
- "Find everything related to learning workflows"
|
||||
- "Show me all high-priority technical content"
|
||||
|
||||
### 4. Bulk Tag Existing Notes
|
||||
|
||||
When user asks to tag untagged notes:
|
||||
|
||||
**Step 1: Discover Files**
|
||||
Use `mcp__obsidian-mcp-tools__list_vault_files` to find markdown files
|
||||
|
||||
**Step 2: Process Each File**
|
||||
For each file:
|
||||
|
||||
1. Use `mcp__obsidian-mcp-tools__get_vault_file` to read content
|
||||
2. Analyze existing frontmatter:
|
||||
- Check if `tags:` field exists
|
||||
- Check if tags are comprehensive (5+ taxonomy tags)
|
||||
3. Skip if already well-tagged (has 5+ taxonomy-compliant tags)
|
||||
4. Analyze content to determine:
|
||||
- Content type (from filename, existing tags, content)
|
||||
- Main topics (2-4 from content analysis)
|
||||
- Status (infer from content or default to `evergreen` for old notes)
|
||||
- Metadata characteristics
|
||||
5. Generate enhanced tag array (5-8 tags total)
|
||||
6. Use `mcp__obsidian-mcp-tools__patch_vault_file` to update frontmatter:
|
||||
|
||||
```
|
||||
mcp__obsidian-mcp-tools__patch_vault_file({
|
||||
filename: "[note-name].md",
|
||||
targetType: "frontmatter",
|
||||
target: "tags",
|
||||
operation: "replace",
|
||||
contentType: "application/json",
|
||||
content: "[{content-type}, {topic1}, {topic2}, {status}, {metadata}]"
|
||||
})
|
||||
```
|
||||
|
||||
**Important Rules:**
|
||||
1. Preserve existing data - merge AI tags with existing tags
|
||||
2. Be conservative - if uncertain, default to `reference`
|
||||
3. Handle errors gracefully - skip invalid files
|
||||
4. Respect user intent - enhance rather than replace
|
||||
|
||||
**Step 3: Report Progress**
|
||||
After every 5-10 files:
|
||||
```
|
||||
✅ Tagged 10 files:
|
||||
- 3 ideas tagged with [idea, productivity, ...]
|
||||
- 2 videos tagged with [video, AI, learning, ...]
|
||||
- 5 articles tagged with [article, development, ...]
|
||||
|
||||
📊 Progress: 10/47 files processed
|
||||
🏷️ Total tags added: 73 tags
|
||||
```
|
||||
|
||||
**Step 4: Final Summary**
|
||||
```markdown
|
||||
# Bulk Tagging Report
|
||||
|
||||
## Summary
|
||||
- **Files processed:** 47
|
||||
- **Files updated:** 43
|
||||
- **Files skipped:** 4 (already well-tagged)
|
||||
- **Total tags added:** 312
|
||||
- **Average tags per note:** 7.3
|
||||
|
||||
## Tag Distribution
|
||||
|
||||
### By Content Type
|
||||
- idea: 15 notes
|
||||
- video: 8 notes
|
||||
- article: 12 notes
|
||||
|
||||
### By Topic
|
||||
- AI: 23 notes
|
||||
- productivity: 18 notes
|
||||
- knowledge-management: 15 notes
|
||||
|
||||
### By Status
|
||||
- inbox: 12 notes
|
||||
- evergreen: 28 notes
|
||||
- published: 7 notes
|
||||
|
||||
## Bases Filtering Suggestions
|
||||
|
||||
You can now create Bases views like:
|
||||
1. **AI Learning Pipeline**: `type = video AND tags contains "AI" AND status = inbox`
|
||||
2. **Quick Wins**: `tags contains "quick-read" AND tags contains "high-priority"`
|
||||
3. **Technical Deep Dives**: `tags contains "technical" AND tags contains "deep-dive"`
|
||||
4. **Actionable Items**: `tags contains "actionable" AND status != archived`
|
||||
```
|
||||
|
||||
### 5. Publish to GitHub Pages
|
||||
|
||||
**Bundled Resources:**
|
||||
- **Script**: `scripts/core/publish.sh` - Complete publish workflow
|
||||
|
||||
When user asks to publish a note:
|
||||
|
||||
**Step 1: Validate Input**
|
||||
|
||||
Add `.md` extension if not provided and verify file exists in vault.
|
||||
|
||||
**Step 2: Run Bundled Publish Script**
|
||||
|
||||
```bash
|
||||
SKILL_DIR="$HOME/.claude/skills/obsidian-vault-manager"
|
||||
"$SKILL_DIR/scripts/core/publish.sh" "$NOTE_FILE"
|
||||
```
|
||||
|
||||
**What the script does:**
|
||||
1. Finds all image references in the note (supports jpg, jpeg, png, gif, svg, webp)
|
||||
2. Copies images from Claudecode vault to sharehub repository (preserves directory structure)
|
||||
3. Converts relative image paths to absolute GitHub Pages URLs:
|
||||
- `./images/file.jpg` → `/sharehub/images/file.jpg`
|
||||
- `images/file.jpg` → `/sharehub/images/file.jpg`
|
||||
4. Copies the note with converted paths to `sharehub/documents/`
|
||||
5. Creates git commit with proper message format
|
||||
6. Pushes to GitHub (triggers GitHub Pages deployment)
|
||||
|
||||
**Step 3: Wait for Deployment**
|
||||
|
||||
```bash
|
||||
# Wait for GitHub Actions to start
|
||||
sleep 3
|
||||
|
||||
# Show recent workflow runs
|
||||
gh run list --limit 3 --repo ZorroCheng-MC/sharehub 2>/dev/null || echo "Install GitHub CLI with: brew install gh"
|
||||
|
||||
echo ""
|
||||
echo "⏳ Waiting 60 seconds for GitHub Pages to deploy..."
|
||||
sleep 60
|
||||
```
|
||||
|
||||
**Step 4: Verify Published Page**
|
||||
|
||||
Use `mcp__MCP_DOCKER__fetch` to verify the page is live:
|
||||
```
|
||||
url: https://zorrocheng-mc.github.io/sharehub/documents/${NOTE_FILE%.md}.html
|
||||
max_length: 2000
|
||||
```
|
||||
|
||||
Check the fetched content for:
|
||||
- Page title matches the note title
|
||||
- Main heading is present
|
||||
- No 404 or error messages
|
||||
- Images are referenced correctly
|
||||
|
||||
**Publishing Paths:**
|
||||
- **Vault**: `/Users/zorro/Documents/Obsidian/Claudecode`
|
||||
- **Sharehub**: `/Users/zorro/Dev/sharehub`
|
||||
- **Repository**: `ZorroCheng-MC/sharehub`
|
||||
- **GitHub Pages**: `https://zorrocheng-mc.github.io/sharehub`
|
||||
|
||||
**Notes:**
|
||||
- This workflow requires filesystem access (works in Claude Code CLI)
|
||||
- For Claude Desktop: Consider using MCP GitHub tools as alternative
|
||||
- Script handles all image copying and path conversion automatically
|
||||
- Git commit includes Claude Code attribution
|
||||
|
||||
## MCP Tools Reference
|
||||
|
||||
### Primary Tools
|
||||
- `mcp__obsidian-mcp-tools__create_vault_file` - Create new notes
|
||||
- `mcp__obsidian-mcp-tools__get_vault_file` - Read note content
|
||||
- `mcp__obsidian-mcp-tools__patch_vault_file` - Update frontmatter/sections
|
||||
- `mcp__obsidian-mcp-tools__search_vault_smart` - Semantic search
|
||||
- `mcp__obsidian-mcp-tools__list_vault_files` - List files
|
||||
- `mcp__MCP_DOCKER__fetch` - Get web content
|
||||
- `mcp__MCP_DOCKER__gitingest-analyze` - Analyze repositories
|
||||
- `mcp__MCP_DOCKER__create_or_update_file` - Create/update single file on GitHub
|
||||
- `mcp__MCP_DOCKER__push_files` - Push multiple files to GitHub in one commit
|
||||
- `mcp__MCP_DOCKER__get_file_contents` - Read files from GitHub
|
||||
- YouTube transcript via bash script (`uvx youtube_transcript_api`)
|
||||
|
||||
## Response Format
|
||||
|
||||
When completing operations:
|
||||
1. **Confirm action**: "✅ Created video note: [title]"
|
||||
2. **Show frontmatter**: Display YAML tags and metadata
|
||||
3. **Provide path**: Show filename and location
|
||||
4. **For publishing**: Include GitHub Pages URL
|
||||
5. **Be concise**: Action-oriented responses
|
||||
|
||||
## Quality Standards
|
||||
|
||||
- **Consistent tagging**: Use ONLY the defined taxonomy
|
||||
- **Correct tag counts**: 5-8 for ideas, 6-8 for videos/study-guides
|
||||
- **Complete frontmatter**: All required YAML fields
|
||||
- **Clean formatting**: Proper markdown structure
|
||||
- **Meaningful titles**: Descriptive, searchable
|
||||
- **Actionable content**: Include next steps where relevant
|
||||
- **Smart defaults**: Medium priority, inbox status for new captures (except study-guides use processing)
|
||||
- **Date stamps**: Always include capture date (YYYY-MM-DD)
|
||||
- **Filename rules**: Follow format for each content type
|
||||
|
||||
## Integration with Bases
|
||||
|
||||
These tags enable powerful Bases filtering queries like:
|
||||
|
||||
- "Show all `inbox` items with `high-priority`"
|
||||
- "Show `video` content about `AI` and `productivity`"
|
||||
- "Show `actionable` items in `processing` status"
|
||||
- "Show `technical` `tutorial` content for learning"
|
||||
|
||||
**Always create tags with filtering in mind.**
|
||||
21
skills/obsidian-vault-manager/scripts/core/fetch-youtube-transcript.sh
Executable file
21
skills/obsidian-vault-manager/scripts/core/fetch-youtube-transcript.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
# Fetch YouTube transcript using youtube_transcript_api
|
||||
# Usage: ./fetch-youtube-transcript.sh VIDEO_ID
|
||||
|
||||
VIDEO_ID="$1"
|
||||
|
||||
if [[ -z "$VIDEO_ID" ]]; then
|
||||
echo "❌ Error: VIDEO_ID required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Fetch transcript using uvx
|
||||
TRANSCRIPT=$(uvx youtube_transcript_api "$VIDEO_ID" --format text 2>&1)
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "❌ Error fetching transcript: $TRANSCRIPT" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Output transcript to stdout
|
||||
echo "$TRANSCRIPT"
|
||||
138
skills/obsidian-vault-manager/scripts/core/publish.sh
Executable file
138
skills/obsidian-vault-manager/scripts/core/publish.sh
Executable file
@@ -0,0 +1,138 @@
|
||||
#!/bin/bash
|
||||
# Publish Obsidian note to GitHub Pages (sharehub)
|
||||
# Handles image copying and path conversion
|
||||
# Usage: ./publish.sh NOTE_FILE
|
||||
|
||||
set -e # Exit on error
|
||||
|
||||
NOTE_FILE="$1"
|
||||
VAULT_PATH="/Users/zorro/Documents/Obsidian/Claudecode"
|
||||
SHAREHUB_PATH="/Users/zorro/Dev/sharehub"
|
||||
|
||||
# Add .md extension if not provided
|
||||
if [[ ! "$NOTE_FILE" =~ \.md$ ]]; then
|
||||
NOTE_FILE="${NOTE_FILE}.md"
|
||||
fi
|
||||
|
||||
# Check if file exists in vault
|
||||
if [[ ! -f "$VAULT_PATH/$NOTE_FILE" ]]; then
|
||||
echo "❌ Error: File not found: $NOTE_FILE"
|
||||
echo "Looking in: $VAULT_PATH/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Found note: $NOTE_FILE"
|
||||
echo ""
|
||||
|
||||
# Extract and copy referenced images
|
||||
cd "$VAULT_PATH"
|
||||
|
||||
# Find all image references (macOS compatible)
|
||||
IMAGE_PATHS=$(grep -o '!\[[^]]*\]([^)]*\.\(jpg\|jpeg\|png\|gif\|svg\|webp\))' "$NOTE_FILE" | sed 's/.*(\(.*\))/\1/' || true)
|
||||
|
||||
if [[ -n "$IMAGE_PATHS" ]]; then
|
||||
echo "📸 Found images to copy:"
|
||||
echo "$IMAGE_PATHS"
|
||||
echo ""
|
||||
|
||||
# Copy each image to sharehub
|
||||
while IFS= read -r IMG_PATH; do
|
||||
# Skip if empty or URL (http/https)
|
||||
if [[ -z "$IMG_PATH" ]] || [[ "$IMG_PATH" =~ ^https?:// ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Normalize path (remove leading ./)
|
||||
CLEAN_PATH="${IMG_PATH#./}"
|
||||
|
||||
# Source path in vault
|
||||
SRC="$VAULT_PATH/$CLEAN_PATH"
|
||||
|
||||
# Destination path in sharehub (preserve directory structure)
|
||||
DEST="$SHAREHUB_PATH/$CLEAN_PATH"
|
||||
DEST_DIR=$(dirname "$DEST")
|
||||
|
||||
if [[ -f "$SRC" ]]; then
|
||||
# Create destination directory if needed
|
||||
mkdir -p "$DEST_DIR"
|
||||
|
||||
# Copy image
|
||||
cp "$SRC" "$DEST"
|
||||
echo " ✅ Copied: $CLEAN_PATH"
|
||||
else
|
||||
echo " ⚠️ Not found: $SRC"
|
||||
fi
|
||||
done <<< "$IMAGE_PATHS"
|
||||
echo ""
|
||||
else
|
||||
echo "ℹ️ No local images found in note"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Read note content
|
||||
NOTE_CONTENT=$(cat "$NOTE_FILE")
|
||||
|
||||
# Convert image paths for GitHub Pages using Python for reliable regex
|
||||
# ./images/file.jpg → /sharehub/images/file.jpg
|
||||
# images/file.jpg → /sharehub/images/file.jpg
|
||||
CONVERTED_CONTENT=$(echo "$NOTE_CONTENT" | python3 -c '
|
||||
import sys, re
|
||||
|
||||
content = sys.stdin.read()
|
||||
|
||||
# Pattern 1: ./path/to/image.ext -> /sharehub/path/to/image.ext
|
||||
content = re.sub(r"!\[([^\]]*)\]\(\./([^)]+\.(jpg|jpeg|png|gif|svg|webp))\)", r"", content, flags=re.IGNORECASE)
|
||||
|
||||
# Pattern 2: path/to/image.ext (no leading ./) -> /sharehub/path/to/image.ext
|
||||
# But skip URLs (http:// or https://)
|
||||
content = re.sub(r"!\[([^\]]*)\]\((?!https?://|/)([^)]+\.(jpg|jpeg|png|gif|svg|webp))\)", r"", content, flags=re.IGNORECASE)
|
||||
|
||||
print(content, end="")
|
||||
')
|
||||
|
||||
echo "📝 Image path conversion complete"
|
||||
echo ""
|
||||
|
||||
# Write converted content to sharehub
|
||||
DEST_NOTE="$SHAREHUB_PATH/documents/$NOTE_FILE"
|
||||
echo "$CONVERTED_CONTENT" > "$DEST_NOTE"
|
||||
|
||||
echo "✅ Copied note to: documents/$NOTE_FILE"
|
||||
echo ""
|
||||
|
||||
# Git operations
|
||||
cd "$SHAREHUB_PATH"
|
||||
|
||||
echo "📋 Git status:"
|
||||
git status --short
|
||||
echo ""
|
||||
|
||||
# Add all changes (document + images)
|
||||
git add "documents/$NOTE_FILE"
|
||||
git add images/ 2>/dev/null || true
|
||||
|
||||
# Get note title from frontmatter for commit message
|
||||
NOTE_TITLE=$(grep -m1 '^title:' "documents/$NOTE_FILE" | sed 's/title: *["'"'"']*//;s/["'"'"']*$//' || echo "$NOTE_FILE")
|
||||
|
||||
# Commit
|
||||
git commit -m "Publish: $NOTE_TITLE
|
||||
|
||||
- Published documents/$NOTE_FILE
|
||||
- Copied associated images
|
||||
- Converted image paths for GitHub Pages
|
||||
|
||||
🤖 Generated with Claude Code
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
# Push to GitHub
|
||||
echo "🚀 Pushing to GitHub..."
|
||||
git push origin main
|
||||
|
||||
echo ""
|
||||
echo "✅ Published successfully!"
|
||||
echo ""
|
||||
echo "📄 Document: https://zorrocheng-mc.github.io/sharehub/documents/${NOTE_FILE%.md}.html"
|
||||
echo "⏱️ GitHub Pages will deploy in ~60 seconds"
|
||||
echo ""
|
||||
|
||||
exit 0
|
||||
82
skills/obsidian-vault-manager/scripts/validation/validate-frontmatter.py
Executable file
82
skills/obsidian-vault-manager/scripts/validation/validate-frontmatter.py
Executable file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Validate frontmatter in markdown content.
|
||||
Can be run by Claude during workflow or configured as a hook in settings.json
|
||||
"""
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
def validate_content(content):
|
||||
"""Validate frontmatter in markdown content"""
|
||||
if not content.startswith("---"):
|
||||
return False, "No frontmatter detected"
|
||||
|
||||
try:
|
||||
# Extract frontmatter
|
||||
parts = content.split("---", 2)
|
||||
if len(parts) < 3:
|
||||
return False, "Malformed frontmatter (missing closing ---)"
|
||||
|
||||
frontmatter = yaml.safe_load(parts[1])
|
||||
|
||||
if not frontmatter:
|
||||
return False, "Empty frontmatter"
|
||||
|
||||
# Required fields
|
||||
required = ["title", "tags", "date", "type"]
|
||||
missing = [f for f in required if f not in frontmatter]
|
||||
|
||||
if missing:
|
||||
return False, f"Missing required fields: {', '.join(missing)}"
|
||||
|
||||
# Validate tags is a list
|
||||
tags = frontmatter.get("tags", [])
|
||||
if not isinstance(tags, list):
|
||||
return False, "Tags must be a list"
|
||||
|
||||
if len(tags) == 0:
|
||||
return False, "Tags list is empty"
|
||||
|
||||
# Check for content type tag
|
||||
valid_types = ["video", "article", "book", "podcast", "idea", "study-guide", "repository", "reference", "project"]
|
||||
has_type = any(tag in valid_types for tag in tags)
|
||||
if not has_type:
|
||||
return False, f"No content type tag found. Expected one of: {', '.join(valid_types)}"
|
||||
|
||||
# Check for inbox tag
|
||||
if "inbox" not in tags:
|
||||
return False, "Warning: 'inbox' tag recommended for new content"
|
||||
|
||||
return True, "✅ Validation passed"
|
||||
|
||||
except yaml.YAMLError as e:
|
||||
return False, f"Invalid YAML syntax: {e}"
|
||||
except Exception as e:
|
||||
return False, f"Validation error: {e}"
|
||||
|
||||
def main():
|
||||
"""Main entry point for validation script"""
|
||||
if len(sys.argv) > 1:
|
||||
# Read from file if provided
|
||||
filename = sys.argv[1]
|
||||
try:
|
||||
with open(filename, 'r') as f:
|
||||
content = f.read()
|
||||
except FileNotFoundError:
|
||||
print(f"❌ Error: File not found: {filename}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
else:
|
||||
# Read from stdin
|
||||
content = sys.stdin.read()
|
||||
|
||||
valid, message = validate_content(content)
|
||||
|
||||
if valid:
|
||||
print(message)
|
||||
sys.exit(0)
|
||||
else:
|
||||
print(f"❌ {message}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
87
skills/obsidian-vault-manager/scripts/validation/validate-mcp-tools.sh
Executable file
87
skills/obsidian-vault-manager/scripts/validation/validate-mcp-tools.sh
Executable file
@@ -0,0 +1,87 @@
|
||||
#!/bin/bash
|
||||
# Validation script to check for common MCP tool name mistakes
|
||||
|
||||
set -e
|
||||
|
||||
SKILL_DIR="$HOME/.claude/skills/obsidian-vault-manager"
|
||||
SKILL_FILE="$SKILL_DIR/SKILL.md"
|
||||
|
||||
echo "🔍 Validating MCP tool names in SKILL.md..."
|
||||
echo ""
|
||||
|
||||
ERRORS=0
|
||||
|
||||
# Check for incorrect Obsidian tool references in MCP_DOCKER
|
||||
if grep -q "mcp__MCP_DOCKER__obsidian" "$SKILL_FILE"; then
|
||||
echo "❌ ERROR: Found MCP_DOCKER__obsidian references!"
|
||||
echo " MCP_DOCKER does not have Obsidian tools."
|
||||
echo " Use: mcp__obsidian-mcp-tools__* instead"
|
||||
echo ""
|
||||
grep -n "mcp__MCP_DOCKER__obsidian" "$SKILL_FILE"
|
||||
echo ""
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
# Check for incorrect gitingest underscore naming
|
||||
if grep -q "mcp__MCP_DOCKER__gitingest_" "$SKILL_FILE"; then
|
||||
echo "❌ ERROR: Found gitingest with underscore!"
|
||||
echo " GitIngest tools use HYPHENS, not underscores."
|
||||
echo " Use: mcp__MCP_DOCKER__gitingest-analyze (with hyphen)"
|
||||
echo ""
|
||||
grep -n "mcp__MCP_DOCKER__gitingest_" "$SKILL_FILE"
|
||||
echo ""
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
# Check for old non-Docker tool references that should be updated
|
||||
if grep -q "mcp__github__create_or_update_file" "$SKILL_FILE"; then
|
||||
echo "⚠️ WARNING: Found old mcp__github__ reference"
|
||||
echo " Consider using: mcp__MCP_DOCKER__create_or_update_file"
|
||||
echo ""
|
||||
grep -n "mcp__github__create_or_update_file" "$SKILL_FILE"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if grep -q "mcp__fetch__fetch" "$SKILL_FILE"; then
|
||||
echo "⚠️ WARNING: Found old mcp__fetch__ reference"
|
||||
echo " Consider using: mcp__MCP_DOCKER__fetch"
|
||||
echo ""
|
||||
grep -n "mcp__fetch__fetch" "$SKILL_FILE"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if grep -q "mcp__gitingest__gitingest-analyze" "$SKILL_FILE"; then
|
||||
echo "⚠️ WARNING: Found old mcp__gitingest__ reference"
|
||||
echo " Consider using: mcp__MCP_DOCKER__gitingest-analyze"
|
||||
echo ""
|
||||
grep -n "mcp__gitingest__gitingest-analyze" "$SKILL_FILE"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
# Verify correct allowed-tools configuration
|
||||
echo "📋 Checking allowed-tools section..."
|
||||
if grep -q "mcp__obsidian-mcp-tools__\*" "$SKILL_FILE"; then
|
||||
echo "✅ Obsidian tools wildcard: CORRECT"
|
||||
else
|
||||
echo "❌ ERROR: Missing mcp__obsidian-mcp-tools__* wildcard!"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
|
||||
if grep -q "mcp__MCP_DOCKER__gitingest-analyze" "$SKILL_FILE"; then
|
||||
echo "✅ GitIngest tool (with hyphen): CORRECT"
|
||||
else
|
||||
echo "⚠️ WARNING: GitIngest tool not found in allowed-tools"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════"
|
||||
|
||||
if [ $ERRORS -eq 0 ]; then
|
||||
echo "✅ Validation PASSED! No errors found."
|
||||
exit 0
|
||||
else
|
||||
echo "❌ Validation FAILED! Found $ERRORS error(s)."
|
||||
echo ""
|
||||
echo "Please review MCP_ARCHITECTURE.md for correct naming"
|
||||
exit 1
|
||||
fi
|
||||
54
skills/obsidian-vault-manager/templates/idea-template.md
Normal file
54
skills/obsidian-vault-manager/templates/idea-template.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: "{{TITLE}}"
|
||||
tags: [idea, {{TOPIC_TAGS}}, inbox, {{METADATA_TAGS}}]
|
||||
date: {{DATE}}
|
||||
type: idea
|
||||
status: inbox
|
||||
priority: {{PRIORITY}}
|
||||
---
|
||||
|
||||
# {{TITLE}}
|
||||
|
||||
## 💡 Core Idea
|
||||
|
||||
{{CORE_IDEA}}
|
||||
|
||||
## 🎯 Why This Matters
|
||||
|
||||
{{WHY_MATTERS}}
|
||||
|
||||
## 🔗 Related Concepts
|
||||
|
||||
{{RELATED_CONCEPTS}}
|
||||
|
||||
## 📝 Next Steps
|
||||
|
||||
{{NEXT_STEPS}}
|
||||
|
||||
## 🏷️ Tags Analysis
|
||||
|
||||
**Content Analysis:**
|
||||
- **Type**: `idea` (Captured thought/concept)
|
||||
- **Topics**: {{TOPICS_EXPLANATION}}
|
||||
- **Characteristics**: {{CHARACTERISTICS_EXPLANATION}}
|
||||
- **Priority**: `{{PRIORITY}}` - {{PRIORITY_EXPLANATION}}
|
||||
|
||||
**Why These Tags:**
|
||||
{{TAG_REASONING}}
|
||||
|
||||
**Suggested Bases Filters:**
|
||||
- Find similar ideas: `type = idea AND tags contains "{{PRIMARY_TOPIC}}"`
|
||||
- Find actionable items: `type = idea AND tags contains "actionable" AND status = inbox`
|
||||
- Find by priority: `priority = {{PRIORITY}} AND status = inbox`
|
||||
- Find by topic combination: `tags contains "{{PRIMARY_TOPIC}}" AND tags contains "{{SECONDARY_TOPIC}}"`
|
||||
|
||||
## 🔍 Related Searches
|
||||
|
||||
- `/semantic-search "{{PRIMARY_TOPIC}} {{SECONDARY_TOPIC}}"`
|
||||
- `/semantic-search "{{RELATED_CONCEPT}}"`
|
||||
|
||||
---
|
||||
|
||||
**Captured**: {{DATE}}
|
||||
**Status**: inbox (needs processing)
|
||||
**Next Action**: Review and categorize, add to relevant project if actionable
|
||||
100
skills/obsidian-vault-manager/templates/study-guide-template.md
Normal file
100
skills/obsidian-vault-manager/templates/study-guide-template.md
Normal file
@@ -0,0 +1,100 @@
|
||||
---
|
||||
title: "Study Guide: {{TITLE}}"
|
||||
tags: [study-guide, {{TOPIC_TAGS}}, processing, {{METADATA_TAGS}}]
|
||||
source: {{SOURCE}}
|
||||
date: {{DATE}}
|
||||
type: study-guide
|
||||
status: processing
|
||||
difficulty: {{DIFFICULTY}}
|
||||
estimated-time: {{ESTIMATED_TIME}}
|
||||
priority: {{PRIORITY}}
|
||||
---
|
||||
|
||||
# Study Guide: {{TITLE}}
|
||||
|
||||
## 📚 Overview
|
||||
|
||||
**Subject:** {{TITLE}}
|
||||
**Source:** {{SOURCE}}
|
||||
**Generated:** {{DATE}}
|
||||
|
||||
### 🎯 Learning Objectives
|
||||
|
||||
By the end of this study session, you will be able to:
|
||||
{{LEARNING_OBJECTIVES}}
|
||||
|
||||
### ⏱️ Study Plan
|
||||
|
||||
- **Total Estimated Time:** {{ESTIMATED_TIME}}
|
||||
- **Difficulty Level:** {{DIFFICULTY}}
|
||||
- **Prerequisites:** {{PREREQUISITES}}
|
||||
- **Recommended Study Method:** {{STUDY_METHOD}}
|
||||
|
||||
## 📋 Content Structure
|
||||
|
||||
{{CONTENT_STRUCTURE}}
|
||||
|
||||
## 💡 Study Strategies
|
||||
|
||||
### For This Material:
|
||||
|
||||
{{MATERIAL_STRATEGIES}}
|
||||
|
||||
### Active Learning Techniques:
|
||||
|
||||
- **Spaced Repetition:** Review key concepts on Day 1, 3, 7, 14
|
||||
- **Practice-Based:** {{PRACTICE_EXERCISES}}
|
||||
- **Teaching Others:** {{TEACHING_TECHNIQUES}}
|
||||
|
||||
## 🧠 Self-Assessment
|
||||
|
||||
### Knowledge Check (Week 1):
|
||||
|
||||
{{WEEK1_ASSESSMENT}}
|
||||
|
||||
### Knowledge Check (Final):
|
||||
|
||||
{{FINAL_ASSESSMENT}}
|
||||
|
||||
## 📊 Progress Tracking
|
||||
|
||||
**Completion Status:**
|
||||
{{PROGRESS_STATUS}}
|
||||
|
||||
**Estimated Progress:** 0%
|
||||
|
||||
**Next Milestone:** {{NEXT_MILESTONE}}
|
||||
|
||||
## 🔗 Related Notes
|
||||
|
||||
{{RELATED_NOTES}}
|
||||
|
||||
## 🏷️ Tags Analysis
|
||||
|
||||
**Content Analysis:**
|
||||
- **Type**: `study-guide` (Structured learning material)
|
||||
- **Topics**: {{TOPICS_EXPLANATION}}
|
||||
- **Difficulty**: {{DIFFICULTY_EXPLANATION}}
|
||||
- **Characteristics**: {{CHARACTERISTICS_EXPLANATION}}
|
||||
- **Priority**: `{{PRIORITY}}` - {{PRIORITY_EXPLANATION}}
|
||||
|
||||
**Why These Tags:**
|
||||
{{TAG_REASONING}}
|
||||
|
||||
**Suggested Bases Filters:**
|
||||
- Find study guides: `type = study-guide AND tags contains "{{PRIMARY_TOPIC}}"`
|
||||
- Find by difficulty: `type = study-guide AND difficulty = {{DIFFICULTY}}`
|
||||
- Find active learning: `type = study-guide AND status = processing`
|
||||
- Find by topic: `tags contains "{{PRIMARY_TOPIC}}" AND tags contains "{{SECONDARY_TOPIC}}"`
|
||||
|
||||
## 🔍 Related Searches
|
||||
|
||||
- `/semantic-search "{{PRIMARY_TOPIC}} {{SECONDARY_TOPIC}}"`
|
||||
- `/semantic-search "{{RELATED_CONCEPT}}"`
|
||||
- `/semantic-search "{{FOUNDATIONAL_TOPIC}}"`
|
||||
|
||||
---
|
||||
|
||||
**Created**: {{DATE}}
|
||||
**Status**: Processing - Active Study
|
||||
**Next Action**: {{NEXT_ACTION}}
|
||||
@@ -0,0 +1,83 @@
|
||||
---
|
||||
title: "{{TITLE}}"
|
||||
tags: [video, {{TOPIC_TAGS}}, inbox, {{METADATA_TAGS}}]
|
||||
url: https://www.youtube.com/watch?v={{VIDEO_ID}}
|
||||
cover: https://i.ytimg.com/vi/{{VIDEO_ID}}/maxresdefault.jpg
|
||||
date: {{DATE}}
|
||||
type: video
|
||||
status: inbox
|
||||
priority: {{PRIORITY}}
|
||||
duration: {{DURATION}}
|
||||
channel: {{CHANNEL}}
|
||||
---
|
||||
|
||||
# {{TITLE}}
|
||||
|
||||
[](https://www.youtube.com/watch?v={{VIDEO_ID}})
|
||||
|
||||
## 📖 Description
|
||||
|
||||
{{DESCRIPTION}}
|
||||
|
||||
**Channel**: {{CHANNEL}}
|
||||
**URL**: https://www.youtube.com/watch?v={{VIDEO_ID}}
|
||||
|
||||
## 🎯 Learning Objectives
|
||||
|
||||
By the end of this video, you will understand:
|
||||
{{LEARNING_OBJECTIVES}}
|
||||
|
||||
## 📋 Curriculum/Contents
|
||||
|
||||
{{CURRICULUM}}
|
||||
|
||||
## 📝 Notes & Key Takeaways
|
||||
|
||||
### Main Insights
|
||||
|
||||
{{MAIN_INSIGHTS}}
|
||||
|
||||
### Actionable Points
|
||||
|
||||
{{ACTIONABLE_POINTS}}
|
||||
|
||||
### Personal Reflections
|
||||
|
||||
*Add your own notes here after watching*
|
||||
|
||||
## ⭐ Rating & Review
|
||||
|
||||
After completion:
|
||||
- **Quality (1-5):** _/5
|
||||
- **Relevance (1-5):** _/5
|
||||
- **Would recommend:** Yes / No
|
||||
- **Best for:** {{TARGET_AUDIENCE}}
|
||||
|
||||
## 🏷️ Auto-Generated Tags
|
||||
|
||||
**Content Analysis:**
|
||||
- **Type**: `video` (YouTube content)
|
||||
- **Topics**: {{TOPIC_ANALYSIS}}
|
||||
- **Complexity**: {{COMPLEXITY_LEVEL}}
|
||||
- **Priority**: {{PRIORITY_REASONING}}
|
||||
|
||||
**Why These Tags:**
|
||||
{{TAG_REASONING}}
|
||||
|
||||
**Suggested Bases Filters:**
|
||||
- Find similar content: `type = video AND tags contains "{{PRIMARY_TOPIC}}"`
|
||||
- Find high-priority learning: `priority = high AND status = inbox`
|
||||
|
||||
## 🔗 Related Topics & Further Research
|
||||
|
||||
**Related Searches:**
|
||||
{{RELATED_SEARCHES}}
|
||||
|
||||
---
|
||||
|
||||
**Captured**: {{DATE}}
|
||||
**Source**: https://www.youtube.com/watch?v={{VIDEO_ID}}
|
||||
**Channel**: {{CHANNEL}}
|
||||
|
||||
**Connection to Other Notes:**
|
||||
{{CONNECTIONS}}
|
||||
Reference in New Issue
Block a user