Operate an Obsidian vault locally (preferred when available) or remotely via GitHub using a bundled gh-based CLI. Use when users ask to list folders, read notes, search content, create/update notes, find project tasks/plans, or move/rename notes in an Obsidian vault.
Resources
3Install
npx skillscat add karlorz/agent-skills/obsidian-gh-knowledge Install via the SkillsCat registry.
Obsidian GitHub Knowledge
Use this skill to operate on an Obsidian vault that is synced to GitHub.
Default behavior:
- If a local vault exists (path from
~/.config/obsidian-gh-knowledge/config.jsonor~/Documents/obsidian_vault/), use local filesystem + local git. - Otherwise, use the GitHub-backed CLI (
gh api/ GitHub code search) via the bundled script.
Note: in sandboxes/containers, the local vault path often does not exist; GitHub mode is expected there.
Mode selection (local vs GitHub)
- Determine local vault directory (
VAULT_DIR):- If
~/.config/obsidian-gh-knowledge/config.jsoncontains"local_vault_path", use it. - Else default to
~/Documents/obsidian_vault/.
- If
- If
VAULT_DIRexists and config"prefer_local"is notfalse, operate locally. - Otherwise, operate remotely (GitHub mode).
In GitHub mode, this skill should NOT guess which repo is your vault.
If the user does not provide --repo (GitHub mode), require the user to either:
- Provide
--repo <owner/repo>explicitly, or - Set up the local config file described below, then use its
default_repo.
Local mode quickstart
VAULT_DIR="$HOME/Documents/obsidian_vault"
ls -la "$VAULT_DIR"
ls -la "$VAULT_DIR/0️⃣-Inbox"
rg -n "keyword" "$VAULT_DIR"
sed -n '1,160p' "$VAULT_DIR/5️⃣-Projects/GitHub/cmux/_Overview.md"For edits, prefer a small commit (feature branch optional in local mode):
cd "$VAULT_DIR"
git status --porcelain=v1
git checkout -b update-notes-YYYYMMDD
git add "path/to/note.md"
git commit -m "Update note"Practical Tips (Paths & Emoji)
- Always wrap
--pathvalues and file paths in quotes (emoji and spaces are common). - Prefer copy/pasting the exact
pathreturned bylist/searchinstead of hand-typing emoji segments. - Treat URL-encoded emoji in API output (e.g.,
%EF%B8%8F%E2%83%A3) as normal. - If you get
HTTP 404, assume the path is wrong or the file does not exist; verify withlistorsearch.
SAFETY RULES (CRITICAL)
These rules prevent accidental data loss. NEVER bypass them.
1. NEVER Force Push to Main
# FORBIDDEN - This can delete all files
gh api -X PATCH repos/.../git/refs/heads/main -F force=true
# FORBIDDEN - Direct reset
git push --force origin main2. ALWAYS Use Feature Branches for GitHub Writes
All write operations MUST use a dedicated feature branch:
write,move,copycommands require--branch <name>- Branch name should be descriptive (e.g.,
update-cmux-docs-20260222) - NEVER commit directly to
main
3. ALWAYS Create PR for Merge
After writing to a branch, create a PR and let user review:
gh pr create --repo <owner/repo> --head <branch> --base main \
--title "Update notes" --body "Changes: ..."NEVER auto-merge without user confirmation.
4. Prefer Local Vault When Available
If a local vault exists at ~/Documents/obsidian_vault/:
- Use local git operations instead of GitHub API
- Commit changes locally first
- Push with
git push(not force push) - This preserves git history and allows easy recovery via
git reflog
5. Read Before Write
Before updating any file:
readthe existing file content- Show diff to user if content differs significantly
- Only proceed with user confirmation for large changes
6. Single-File Operations Only
- Write/move/copy ONE file per commit
- NEVER batch multiple unrelated files in one branch
- This makes rollback easier if something goes wrong
Obsidian Note Authoring Guidelines
When creating or editing notes in an Obsidian vault, follow these conventions:
- If the workspace/repo has an
AGENTS.md, read it and follow it (it overrides these defaults).
Markdown
- Prefer a short
## TL;DRnear the top for human scanning. - Use Obsidian wikilinks (
[[note-title]]) for internal references instead of raw URLs. - Keep headings stable; rename/move only when explicitly asked (links depend on titles/paths).
- Use YAML frontmatter for metadata (tags, aliases, dates).
Mermaid (Obsidian Compatibility)
Obsidian's Mermaid renderer has quirks. Follow these rules to avoid rendering failures:
- Prefer
graph TB/sequenceDiagramover newer Mermaid syntaxes. - Avoid
subgraph ID[Label]style; use quoted titles:subgraph "Title". - Avoid
\nin node labels; use<br/>or keep labels single-line. - Avoid parentheses and slashes in node labels; Obsidian chokes on
(...)ora/binside[...]. - Keep node IDs ASCII and simple (
OC_GW,CMUX_DB); avoid punctuation in IDs. - If a diagram fails to render, simplify first (remove subgraphs/line breaks), then add complexity back.
Vault Organization Conventions
Typical Obsidian vault folder structure (emoji prefixes for sorting):
| Directory | Purpose |
|---|---|
0️⃣-Inbox/ |
Uncategorized new notes |
1️⃣-Index/ |
Maps of content (MOCs), overviews |
2️⃣-Drafts/ |
Work-in-progress ideas |
3️⃣-Plugins/ |
Plugin docs and configs |
4️⃣-Attachments/ |
Non-image assets (PDFs, sheets) |
5️⃣-Projects/ |
Project documentation by category |
assets/ |
Images and media |
100-Templates/ |
Reusable note templates |
Project Folder Convention (5️⃣-Projects/)
Each project folder MUST have a _Overview.md file as its Map of Content (MOC):
5️⃣-Projects/
├── GitHub/
│ ├── cmux/
│ │ ├── _Overview.md # MOC index (required)
│ │ ├── cmux-tech-stack.md
│ │ └── ...
│ └── openclaw/
│ ├── _Overview.md # MOC index (required)
│ ├── openclaw-local-status.md
│ └── ...
├── Infrastructure/
│ └── k8s/
│ └── _Overview.md
└── Research/
└── _Overview.md_Overview.md Template Structure:
- Start with
# Project Name (MOC)heading - Use
> [!info] Map of Contentcallout with project metadata (repo, stack, updated date) - Include Quick Navigation table linking key documents
- Include Documentation Index with Status column (Current, Reference, Active, etc.)
- Add architecture diagram (Mermaid) if applicable
- Include Cross-References section by topic
- End with Document Status Legend and Last Updated date
When creating a new project folder:
- Create the folder under appropriate category (GitHub, Infrastructure, Research)
- Create
_Overview.mdas the first file - Follow the MOC template structure
- Link all related documents from the overview
When creating new notes:
- Place uncategorized notes in
Inboxfor later review. - Use links and tags for navigation, not deep folder nesting.
- Check existing structure with
listbefore assuming folder names.
Templates
- For GitHub project notes, read and use
100-Templates/github-project-template.mdas the starting structure. - Read the template:
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo <owner/repo> read \ "100-Templates/github-project-template.md" - To scaffold a new project folder with
_Overview.md:# Create the _Overview.md as the MOC index python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo <owner/repo> copy \ "100-Templates/github-project-template.md" \ "5️⃣-Projects/GitHub/<project>/_Overview.md" \ --branch "add-project-docs" \ --message "Add project overview MOC" - For additional notes in the project folder:
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo <owner/repo> write \ "5️⃣-Projects/GitHub/<project>/<note-name>.md" \ --stdin \ --branch "add-project-docs" \ --message "Add project note"
Repo Resolution Policy
Resolve the repository in this order:
- If the user provides
--repo <owner/repo>, use it. - If the user provides
--repo <key>(no/), resolve it via~/.config/obsidian-gh-knowledge/config.jsonatrepos.<key>. - If
--repois omitted, usedefault_repofrom the same config file. - If none of the above is available, ask the user for the repo or ask them to set local config.
Never guess repo names.
Requirements
- GitHub CLI installed:
gh - Authenticated:
gh auth status
Commands
GitHub mode operations are performed via the bundled script:
python3 scripts/github_knowledge_skill.py --repo <owner/repo> <command> [args]If the skill is installed globally, the script is typically located at:
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo <owner/repo> <command> [args]list --path <path>: List files in a directory.read <file_path>: Read file content.search <query>: Search code/content.move <src> <dest> --branch <branch_name> --message <commit_msg>: Move/rename a file by creating the destination file and deleting the source file on a branch.copy <src> <dest> --branch <branch_name> --message <commit_msg>: Copy a file by creating the destination file on a branch.write <file_path> --stdin|--from-file <path> --branch <branch_name> --message <commit_msg>: Create or update a file on a branch.
Repo Selection (Local Config)
To avoid hard-coding a personal repo in prompts, store your vault repo(s) locally and have the agent/tooling read it.
First-time setup: create ~/.config/obsidian-gh-knowledge/config.json:
{
"default_repo": "<owner>/<vault-repo>",
"repos": {
"personal": "<owner>/<vault-repo>",
"work": "<org>/<work-vault-repo>"
},
"local_vault_path": "~/Documents/obsidian_vault",
"prefer_local": true
}Usage (resolve repo at runtime):
REPO="$(python3 -c 'import json,os; p=os.path.expanduser("~/.config/obsidian-gh-knowledge/config.json"); print(json.load(open(p))["default_repo"])')"
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" list --path "0️⃣-Inbox"If the user specifies a repo key (e.g., work), resolve it from repos.<key> instead of default_repo.
Example (resolve repo key):
REPO="$(python3 -c 'import json,os; p=os.path.expanduser("~/.config/obsidian-gh-knowledge/config.json"); c=json.load(open(p)); print(c["repos"]["work"])')"
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" search "dev plan"Quick Workflow Example
When asked to find and read a note:
List to discover exact paths:
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" list --path "1️⃣-Index"Search if the path is unknown:
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" search "MOC"Read the target file:
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" read "1️⃣-Index/README.md"
Search Query Tips
The search command uses GitHub code search. Include qualifiers directly in your query string:
# Search in specific folder
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" search "TODO path:1️⃣-Index/"
# Search project notes
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" search "project plan path:5️⃣-Projects/ extension:md"
# Find all project overviews
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" search "filename:_Overview.md"
# Find specific project overview
python3 ~/.agents/skills/obsidian-gh-knowledge/scripts/github_knowledge_skill.py --repo "$REPO" search "filename:_Overview.md path:5️⃣-Projects/GitHub/cmux"Workflow Reference
See references/obsidian-organizer.md for a concrete organizing workflow that uses these commands.
Notes
searchuses GitHub code search; results may be empty for new commits until GitHub indexes them (typically seconds to minutes).- Qualifiers like
path:,extension:,filename:can narrow results - include them directly in the query string. - Paths must match the repo exactly (including emoji and normalization). Use
listto discover the exact directory names. - Every project folder under
5️⃣-Projects/MUST have a_Overview.mdfile as its MOC index. - When creating new project documentation, always create
_Overview.mdfirst, then add related notes.
Recovery Procedures
If files are accidentally deleted or corrupted:
From Local Vault (Preferred)
cd ~/Documents/obsidian_vault
git reflog # Find good commit
git reset --hard <commit-sha> # Restore locally
git push --force origin main # Sync to remote (only if local is source of truth)From Remote (if local is lost)
# List commits to find pre-deletion state
gh api repos/<owner>/<repo>/commits --jq '.[].sha' | head -10
# Check file count at each commit
gh api repos/<owner>/<repo>/git/trees/<sha>?recursive=1 --jq '.tree | length'
# Reset remote to good commit (DANGEROUS - confirm with user first)
gh api -X PATCH repos/<owner>/<repo>/git/refs/heads/main \
-F sha=<good-commit-sha> -F force=trueComparison: GitHub API vs Local Git
| Operation | GitHub API | Local Git |
|---|---|---|
| Recovery | Hard (no reflog) | Easy (reflog) |
| Atomic commits | Per-file only | Multi-file |
| Speed | Slower (HTTP) | Faster |
| Offline | No | Yes |
| Audit trail | Limited | Full |
Recommendation: When ~/Documents/obsidian_vault/ exists, prefer local git operations.