Obsidian
Skill furkangonel/cowrangler/bundled_skills/note-taking/obsidian
Autonomous terminal AI agent for workflows and feasible project procedures. Co-Worker Co-Wrangler π
npx -y skills add furkangonel/cowrangler --skill obsidianAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Obsidian vault management β create notes, backlinks, tags, and Dataview queries via file operations
SKILL.md
6.0 KB, ~1.6k tokens by cl100k_base, as published. Nobody here has run it
Obsidian Vault Management
Goal
Create, update, and organize notes in an Obsidian vault programmatically. Query notes with Dataview syntax. Maintain a consistent vault structure.
Vault Structure
vault/
βββ Daily Notes/ # YYYY-MM-DD.md
βββ Projects/ # One folder per project
βββ Areas/ # Ongoing responsibilities
βββ Resources/ # Reference material
βββ Archive/ # Inactive notes
βββ _templates/ # Note templates
Use PARA method (Projects / Areas / Resources / Archive) as the default organization.
Frontmatter Conventions
Every note should have frontmatter:
---
title: Note Title
date: 2024-01-15
tags: [topic, subtopic]
aliases: [alternative-name]
status: draft | active | archived
related: [[Other Note]], [[Another Note]]
---
date: ISO 8601 (YYYY-MM-DD)tags: lowercase, hyphenatedaliases: alternate names for search/linkingstatus: lifecycle staterelated: explicit links (supplement to inline wikilinks)
Creating Notes Programmatically
Basic note creation
from pathlib import Path
from datetime import datetime
def create_note(vault_path: str, folder: str, title: str, content: str, tags: list[str] = []) -> Path:
vault = Path(vault_path)
target_dir = vault / folder
target_dir.mkdir(parents=True, exist_ok=True)
# Sanitize title for filename
filename = title.replace("/", "-").replace(":", "-") + ".md"
note_path = target_dir / filename
frontmatter = f"""---
title: {title}
date: {datetime.now().strftime("%Y-%m-%d")}
tags: {tags}
---
"""
note_path.write_text(frontmatter + content, encoding="utf-8")
return note_path
Daily note
def create_daily_note(vault_path: str, template: str = "") -> Path:
today = datetime.now().strftime("%Y-%m-%d")
content = template or f"""# {today}
## Tasks
- [ ]
## Notes
## Links
"""
return create_note(vault_path, "Daily Notes", today, content)
Wikilink Syntax
[[Note Title]] # Basic link
[[Note Title|Display Text]] # Link with alias
[[Note Title#Heading]] # Link to section
![[Note Title]] # Embed note
![[image.png]] # Embed image
Adding backlinks programmatically
def add_backlink(note_path: str, linked_title: str):
path = Path(note_path)
content = path.read_text(encoding="utf-8")
link = f"[[{linked_title}]]"
if link not in content:
content += f"\n\n## Related\n{link}\n"
path.write_text(content, encoding="utf-8")
Tag Management
import re
def add_tags(note_path: str, new_tags: list[str]):
path = Path(note_path)
content = path.read_text(encoding="utf-8")
# Find existing tags in frontmatter
match = re.search(r'^tags:\s*\[([^\]]*)\]', content, re.MULTILINE)
if match:
existing = [t.strip() for t in match.group(1).split(",") if t.strip()]
merged = list(set(existing + new_tags))
content = content[:match.start()] + f"tags: {merged}" + content[match.end():]
path.write_text(content, encoding="utf-8")
def find_notes_by_tag(vault_path: str, tag: str) -> list[Path]:
vault = Path(vault_path)
results = []
for md in vault.rglob("*.md"):
if f"#{tag}" in md.read_text() or f'"{tag}"' in md.read_text():
results.append(md)
return results
Dataview Queries
Dataview plugin queries (placed inside dataview code blocks in notes):
List notes by tag
```dataview
LIST
FROM #project
SORT date DESC
```
Table of tasks
```dataview
TABLE date, status, tags
FROM "Projects"
WHERE status != "archived"
SORT date DESC
```
Incomplete tasks across vault
```dataview
TASK
WHERE !completed
FROM "Projects"
GROUP BY file.link
```
Notes modified this week
```dataview
LIST
WHERE file.mtime >= date(today) - dur(7 days)
SORT file.mtime DESC
```
Search and Query (CLI)
# Find all notes containing a phrase
grep -rl "search term" /path/to/vault --include="*.md"
# Find broken wikilinks (links with no matching file)
python3 << 'EOF'
from pathlib import Path
import re
vault = Path("/path/to/vault")
all_titles = {p.stem for p in vault.rglob("*.md")}
wikilink_pattern = re.compile(r'\[\[([^\]|#]+)')
for note in vault.rglob("*.md"):
content = note.read_text()
for link in wikilink_pattern.findall(content):
if link.strip() not in all_titles:
print(f"Broken link in {note.name}: [[{link}]]")
EOF
Templates
Meeting note template
---
title: Meeting β {{title}}
date: {{date}}
tags: [meeting]
attendees: []
---
# {{title}}
**Date**: {{date}}
**Attendees**:
## Agenda
1.
## Notes
## Action Items
- [ ]
## Decisions
Project note template
---
title: {{project-name}}
date: {{date}}
tags: [project]
status: active
deadline:
---
# {{project-name}}
## Goal
## Success Criteria
- [ ]
## Tasks
- [ ]
## Notes
## Related
Folder Organization Patterns
| Content Type | Location | Naming |
|---|---|---|
| Daily notes | Daily Notes/ | YYYY-MM-DD.md |
| Meeting notes | Areas/Meetings/ | YYYY-MM-DD Topic.md |
| Project notes | Projects/{name}/ | README.md + sub-notes |
| Reference | Resources/{topic}/ | Descriptive title |
| Permanent notes | Resources/Zettelkasten/ | ID + title |
Common Pitfalls
- Spaces in filenames: Obsidian handles them, but some plugins prefer hyphens
- Nested tags: Use
#category/subcategorysyntax for hierarchy - Sync conflicts: Prefer iCloud or Obsidian Sync over Dropbox for vault sync
- Large vaults: Limit graph view for vaults >5000 notes; use search instead