upgrade
The upgrade skill pulls the latest claudesidian from GitHub and intelligently merges upstream changes into the user's vault while preserving customizations through semantic analysis. Use this when updating claudesidian to a newer version, incorporating upstream improvements, or syncing local installations with the main repository without losing personalized skills, settings, or content folders.
git clone --depth 1 https://github.com/heyitsnoah/claudesidian /tmp/upgrade && cp -r /tmp/upgrade/.agents/skills/upgrade ~/.claude/skills/upgradeSKILL.md
# Smart Upgrade
Pulls the latest claudesidian from GitHub and merges it into the user's vault,
preserving customizations.
## Layout assumptions (READ FIRST)
claudesidian stores skills under **`.agents/skills/<name>/SKILL.md`** as the
canonical location. Symlinks live at `.claude/skills/<name>` and
`.pi/skills/<name>` pointing back to canonical. Edit canonical, all consumers
follow.
If the user is on a pre-conversion claudesidian (anything before the
commands→skills migration) they will have `.claude/commands/*.md` instead and
no `.agents/skills/`. **Do not run a normal upgrade in that case** — see
"Migration from legacy layout" at the bottom of this file.
If the user's local repo has `.agents/skills/` populated, proceed normally.
## Process
### 1. Version check
- Read current version from `package.json`
- Fetch upstream version:
```bash
CURRENT=$(grep '"version"' package.json | head -1 | cut -d'"' -f4)
LATEST=$(curl -s https://raw.githubusercontent.com/heyitsnoah/claudesidian/main/package.json | grep '"version"' | head -1 | cut -d'"' -f4)
if [ "$CURRENT" = "$LATEST" ]; then
echo "✅ Already on $CURRENT"
exit 0
fi
```
- Detect layout: `test -d .agents/skills && echo NEW || echo LEGACY`. If
LEGACY, jump to "Migration from legacy layout".
### 2. Backup
```bash
BACKUP_DIR=".backup/upgrade-$(date +%Y-%m-%d-%H%M%S)"
mkdir -p "$BACKUP_DIR"
cp -r .agents .claude .pi .scripts package.json "$BACKUP_DIR/" 2>/dev/null
cp CHANGELOG.md README.md "$BACKUP_DIR/" 2>/dev/null || true
echo "✅ Backup created at $BACKUP_DIR"
```
### 3. Fetch upstream
```bash
git clone --depth=1 --branch=main \
https://github.com/heyitsnoah/claudesidian.git \
.tmp/claudesidian-upgrade
```
The user's working repo stays disconnected from origin throughout — we only
ever read from `.tmp/`.
### 4. Build upgrade checklist
System files we care about:
- **Skills**: `.agents/skills/<name>/SKILL.md` (canonical) — also resources
inside skill dirs (helper scripts, references).
- **Hooks**: `.claude/hooks/*.sh`
- **Settings**: `.claude/settings.json`
- **MCP servers**: `.claude/mcp-servers/*`
- **Scripts**: `.scripts/*`
- **Core**: `package.json`, `CHANGELOG.md`, `README.md`
Files we **never touch**:
- User content folders: `00_Inbox/`, `01_Projects/`, `02_Areas/`,
`03_Resources/`, `04_Archive/`, `05_Attachments/`, `06_Metadata/` (except
`06_Metadata/Templates/` if upstream changes them)
- The user's `CLAUDE.md`
- `.obsidian/` (user's Obsidian settings)
- `vault-config.json`
- `.mcp.json` (contains API keys)
- Anything in `.git/`
Build the checklist:
```bash
# Skills that exist in both, or only upstream, or only local
diff -qr .agents/skills .tmp/claudesidian-upgrade/.agents/skills 2>/dev/null
# Hooks, settings, mcp-servers, scripts
diff -qr .claude/hooks .tmp/claudesidian-upgrade/.claude/hooks 2>/dev/null
diff -q .claude/settings.json .tmp/claudesidian-upgrade/.claude/settings.json 2>/dev/null
diff -qr .claude/mcp-servers .tmp/claudesidian-upgrade/.claude/mcp-servers 2>/dev/null
diff -qr .scripts .tmp/claudesidian-upgrade/.scripts 2>/dev/null
# Core files
diff -q package.json .tmp/claudesidian-upgrade/package.json
diff -q README.md .tmp/claudesidian-upgrade/README.md
diff -q CHANGELOG.md .tmp/claudesidian-upgrade/CHANGELOG.md
```
Write findings to `.upgrade-checklist.md`, grouped by category, with status
markers `[ ] pending`, `[x] updated`, `[-] skipped`.
### 5. File-by-file review
**Hard rules — do not skip:**
- Always show the diff before modifying anything.
- Always wait for the user's choice. Never auto-pick.
- Never use `cp -f`. Use `cat src > dest` for non-interactive overwrite.
- Update `.upgrade-checklist.md` after every file.
For each file in the checklist:
1. Show `diff -u local upstream`.
2. Determine state:
- **No local edits, no upstream edits** → mark `[-]` skipped, move on.
- **Upstream changed, no local edits** → ask: apply / keep / view full
diff.
- **Both changed (local customization)** → ask: keep yours / take upstream
/ view full diff / AI-merge.
3. Ask the user:
```
File: <path> has updates.
1. Apply update (take upstream)
2. Keep your version
3. View full diff
4. AI-merge
Choice (1/2/3/4):
```
**Wait for input. Do not auto-select.**
4. Apply the chosen action:
```bash
# Option 1
if [ -f ".tmp/claudesidian-upgrade/$path" ]; then
mkdir -p "$(dirname "$path")"
cat ".tmp/claudesidian-upgrade/$path" > "$path"
echo "✅ Updated $path"
fi
```
5. Mark in checklist and continue.
### 6. Symlink hygiene (skills only)
After updating any skill in `.agents/skills/<name>/`, verify the symlinks in
`.claude/skills/<name>` and `.pi/skills/<name>` still resolve:
```bash
for name in $(ls .agents/skills); do
for agent in claude pi; do
link=".${agent}/skills/${name}"
target="../../.agents/skills/${name}"
mkdir -p ".${agent}/skills"
if [ -L "$link" ]; then
# Symlink exists — verify it points to the right place
current="$(readlink "$link")"
if [ "$current" != "$target" ]; then
rm "$link"
ln -s "$target" "$link"
echo "✅ Repaired symlink $link (was → $current)"
fi
elif [ -e "$link" ]; then
# Real file or directory at this path — do not trample user data
echo "⚠️ $link exists as a real file/dir, not a symlink. Skipping."
echo " Manual fix: inspect, back up if needed, then rm and rerun."
else
# Nothing there — create
ln -s "$target" "$link"
echo "✅ Created symlink $link"
fi
done
done
```
The `-L` test is critical: a broken symlink (target missing) returns false from
`-e` but true from `-L`, so checking `-e` alone would try to `ln -s` over the
existing broken link and fail with "File exists". Conversely, a symlink
pointing the wrong way would pass `-e` (because the wrong target still exists)
and silently stay wrong. Always check `-L` first, then verify the target with
`readlink`, then falAdd or update YAML frontmatter properties to enhance Obsidian note organization. Use when the user asks to add, fix, normalize, or improve frontmatter, properties, metadata, tags, or YAML on a note or folder of notes.
Conduct an end-of-day review to capture progress and set up tomorrow. Use when the user asks for a daily review, end of day wrap-up, EOD note, what they did today, or wants to reflect on the day and plan tomorrow.
Remove AI-generated jargon and restore human voice to text. Use when the user asks to de-AI-ify, humanize, remove AI tone, or make text sound less machine-generated.
Download files from URLs to the Obsidian attachments folder and organize them with descriptive names. Use when the user provides URLs to download, asks to save files from the web, or wants to add web content as attachments.
Work with git worktrees for isolated parallel development. Use when starting feature work in isolation, when need separate workspace without branch switching, or when cleaning up worktrees after PR merge.
Help organize and process items in the 00_Inbox folder according to the PARA method. Use when the user asks to process, clear, sort, triage, or organize their inbox.
Interactive setup wizard that helps new users create a personalized CLAUDE.md file based on their Obsidian workflow preferences. Use when the user wants to set up claudesidian, onboard a new vault, or run the bootstrap/init/setup wizard.
Install claudesidian shell command to launch Claude Code from anywhere. Use when the user wants to install a shell alias/launcher for their vault, or asks to set up the claudesidian command.