From workflow
Scan, classify, enrich, and file Obsidian notes from Inbox/ and the vault root into the PARA folder structure. Use when the user wants to process their inbox, triage notes, or organize unfiled content. Triggers on "process inbox", "triage notes", "file inbox", "organize notes", "clean up inbox".
npx claudepluginhub shortrib-labs/shortrib-claude-marketplace --plugin workflowThis skill is limited to using the following tools:
Scan, classify, and file Obsidian notes from Inbox/ and the vault root into the PARA folder structure. Every note move goes through the Obsidian CLI to preserve wiki-links.
Creates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
Scan, classify, and file Obsidian notes from Inbox/ and the vault root into the PARA folder structure. Every note move goes through the Obsidian CLI to preserve wiki-links.
Parse $ARGUMENTS for:
--dry-run: Classify and report without moving anything. Print what would happen.--batch-size N: Maximum notes to process per run. Default: 25.Before doing anything else:
Check Obsidian is running. Run obsidian vault. If it returns non-zero, stop immediately and report: "Obsidian is not running. Start Obsidian and try again." Do not attempt to launch Obsidian.
Load the Obsidian CLI reference. Read ${CLAUDE_PLUGIN_ROOT}/skills/obsidian/SKILL.md for command syntax. Use path= (not file=) for all CLI operations to get deterministic path resolution.
Load reference files. Read both files from the skill directory:
${CLAUDE_PLUGIN_ROOT}/skills/inbox-process/classification-rules.md${CLAUDE_PLUGIN_ROOT}/skills/inbox-process/frontmatter-schema.mdBuild a complete picture of the vault before processing any notes.
Run obsidian folders to get the full folder tree. Identify:
Find and read the PARA Design document. It may be at Inbox/PARA Design.md or already filed elsewhere. Search with obsidian search query="PARA System Design" limit=3 if not at the expected path.
Extract from the PARA Design doc:
Collect all notes in scope:
obsidian files folder="Inbox" ext=md to list Inbox notes.ls /Users/chuck/workspace/vaults/Notes/*.md 2>/dev/null to list vault root markdown files (the CLI may not reliably enumerate root files).Exclude from processing:
PARA Design.md and PARA Operating Manual.md (reference docs, skip)favorite.md and any Obsidian system files at vault root.md fileSort the combined list alphabetically by filename for deterministic processing order. Trim to --batch-size limit.
Report: "Found N notes to process (M in Inbox, K at vault root). Batch size: B."
Process each note one at a time in alphabetical order. For each note:
Read the note's full content with obsidian read path="<vault-relative-path>". Parse:
obsidian links path="<vault-relative-path>"![[filename]] patterns in the bodyUsing the classification rules (loaded in Phase 1), determine the best PARA destination folder.
Your classification judgment should weigh:
type, tags, related)Apply PARA priority: Projects > Areas > Resources.
If no existing subfolder is a confident match:
mkdir -p.If the note is empty or has only frontmatter with no content: Skip and log "empty, needs manual review."
If classification is truly ambiguous: Skip and log "needs manual filing" with a brief explanation of the ambiguity.
Apply the frontmatter schema (loaded in Phase 1):
Ensure all canonical fields exist. For each missing canonical field, set it:
date: Use existing value, or file creation date, or todaytype: Infer from content analysis (meeting, brief, research, etc.)tags: Start with existing tags, add tags from PARA taxonomy that match contentlast_updated: Set to today (YYYY-MM-DD)status: Use default status for the inferred type (see schema)aliases: Only add if there's an obvious abbreviation or short nameMerge, don't overwrite. If a field already has a value:
tags: Append new tags to existing list, deduplicatetype/status: If the existing value matches the controlled vocabulary, keep it. If unrecognized, preserve and log a warning.date: Preserve the existing format (don't fight the Obsidian Linter)Rename known synonyms. If link field exists, rename to url using the three-step process: read, set new, remove old.
Preserve non-canonical fields. Never remove fields you don't recognize.
Use obsidian property:set for each field that needs setting. Use path= for deterministic resolution.
For list-type fields (tags, aliases), use type=list with obsidian property:set. If append behavior is uncertain, read the current value first, merge in memory, then write the complete list.
In dry-run mode: Print the proposed move and skip to the next note.
[DRY RUN] Would move: "Note Title" -> Projects/Salesforce to Attio Migration/ (type: meeting, tags: [attio, sync])
In normal mode:
mkdir -p "<vault-path>/<destination>/"obsidian move path="<current-path>" to="<destination-folder>/"![[image.png]] patterns):
a. Resolve each attachment's current location (check Inbox/attachments/, Inbox/, or relative to the note)
b. Validate the resolved path is within the vault boundary (reject any path containing .. that escapes the vault)
c. Check if the attachment is referenced by other notes (search for ![[filename]] across the vault)
d. If shared by multiple notes going to different destinations, leave in place and log "shared attachment, left in place"
e. If not shared: mkdir -p "<destination>/attachments/" then mv "<source>" "<destination>/attachments/"Error handling: If any step fails for a note, log the error and continue to the next note. Do not abort the run.
Track each processed note for the Phase 3 report:
Print a summary to the terminal:
## Inbox Processing Complete
Processed: N | Skipped: M | Errors: E | New folders: F
### Moved
| Note | From | To | Type |
|------|------|----|------|
| Note Title | Inbox/ | Projects/Attio Migration/ | meeting |
| ...
### Skipped (if any)
| Note | Reason |
|------|--------|
| Empty Note | empty, needs manual review |
| ...
### Warnings (if any)
- Note X has unrecognized type 'foo', preserved as-is
- Shared attachment image.png left in place (referenced by Note A and Note B)
### New Folders Created (if any)
- Resources/New Topic/
In dry-run mode, prefix the summary with [DRY RUN] No changes were made. and show the "Would move" table instead.
Skip this step in dry-run mode.
Append results to ~/.local/share/inbox-process/logs/YYYY-MM.md (using the current year-month).
Create the directory if it doesn't exist: mkdir -p ~/.local/share/inbox-process/logs/
If the log file doesn't exist yet, create it with a top-level heading: # Inbox Processing Log - YYYY-MM
Append a run entry:
## YYYY-MM-DD HH:MM
| Note | From | To | Type | New Folder |
|------|------|----|------|------------|
| Note Title | Inbox/ | Projects/Attio Migration/ | meeting | |
| Other Note | Inbox/ | Resources/New Topic/ | concept | yes |
Processed: N | Skipped: M | Errors: E | New folders: F
After all moves are complete (not in dry-run mode), run obsidian reload to trigger vault reindexing. This ensures Obsidian picks up all the file moves and new folders.
/Users/chuck/workspace/vaults/Notes/). Reject any path containing .. segments that would escape the vault.