- name
- gobi-migration
- description
- Set up a new AI4PKM vault from scratch or migrate an existing vault to the latest template version. Detects current state, generates a plan, and applies changes with full backup safety.
- metadata
- {"version":"1.2.0","author":"lifidea","created":"2026-03-18T00:00:00.000Z","target_version":"0.0.30"}
# Gobi Migration Skill
Set up a new AI4PKM vault from scratch **or** migrate an existing vault to v0.0.30. The skill operates in two modes:
- **Fresh Install**: For new users — scaffolds the full vault structure, fetches all template files from GitHub, and runs onboarding
- **Upgrade**: For existing users — detects the current version, identifies which structural epochs are needed, and applies changes incrementally with full backup safety
## Prerequisites
- **GitHub CLI (`gh`)** must be installed and authenticated — used to fetch template files
- **Gobi CLI (`gobi`)** must be installed for community features (spaces, brains, sessions)
```bash
npm install -g @gobi-ai/cli
# or: brew tap gobi-ai/tap && brew install gobi
```
Verify: `gobi --version` — see [gobi-cli repo](https://github.com/gobi-ai/gobi-cli) for details
- **Template repo**: `jykim/ai4pkm-vault` (public)
- This skill runs **standalone in any user vault** — it does NOT require being inside the template repo
## When to Use
- User says "볼트 마이그레이션", "vault migration", or "migrate vault"
- User asks to upgrade an older vault to the latest template
- User cloned the template long ago and wants new Gobi features
- After `vault-update` (file-level) when structural changes are also needed
- User says "볼트 설정", "vault setup", or "set up vault"
- User says "새 볼트", "new vault", or "fresh install"
- User is in an empty directory and asks for help setting up a PKM vault
## Quick Commands
```markdown
"볼트 설정" / "setup vault" → Fresh install flow
"마이그레이션" / "migrate" → Upgrade flow (existing)
"마이그레이션 상태" / "migration status" → Detect version and show what's needed
"마이그레이션 검증" / "verify migration" → Run verification checklist
```
## Relationship to vault-update
| Concern | vault-update (ai4pkm-cli) | gobi-migration (this skill) |
|---------|--------------------------|----------------------------|
| Scope | File-level: fetch/overwrite files from GitHub release | Structural: merge configs, create folders, add nodes |
| When | New release available | Vault structure outdated |
| Prompts/Skills | Downloads latest versions | Delegates to vault-update or fetches from GitHub |
| orchestrator.yaml | Overwrites (with conflict check) | Merges (preserves custom nodes) |
| AGENTS.md | Overwrites (with conflict check) | Section-level merge |
**Recommended order**: Run `gobi-migration` first (structural), then `vault-update` (file content).
## Fetching Template Files from GitHub
When the migration needs a template file (prompt, base, config), fetch it from the repo:
```bash
# Fetch a single file's content (decoded from base64)
gh api "repos/jykim/ai4pkm-vault/contents/{path}?ref=main" -q '.content' | base64 -d
# Examples:
gh api "repos/jykim/ai4pkm-vault/contents/orchestrator.yaml?ref=main" -q '.content' | base64 -d
gh api "repos/jykim/ai4pkm-vault/contents/AGENTS.md?ref=main" -q '.content' | base64 -d
gh api "repos/jykim/ai4pkm-vault/contents/BRAIN.md?ref=main" -q '.content' | base64 -d
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Prompts/Post%20Brain%20Update%20(PBU).md?ref=main" -q '.content' | base64 -d
# List directory contents
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Prompts?ref=main" -q '.[].name'
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Bases?ref=main" -q '.[].name'
```
**Important**: Always wrap `gh api` URLs in double quotes. URLs containing `?ref=main` will cause shell glob expansion errors if unquoted, potentially resulting in empty responses and 0-byte files.
**Always fetch from `main` branch** to get the latest template state. URL-encode spaces as `%20` in paths.
---
## Migration Flow
### Step 0: Vault Root Detection
Before anything else, confirm we're operating in the correct directory.
**Detection logic**:
1. Check CWD for `orchestrator.yaml` or `.obsidian/`
2. If not found, walk parent directories (max 5 levels) looking for the same markers
3. Interpret results:
| Found | Where | Interpretation |
|-------|-------|---------------|
| `orchestrator.yaml` | CWD | Confirmed vault root — proceed |
| `orchestrator.yaml` | Parent dir | Ask user to confirm path before proceeding |
| `.obsidian/` only | CWD or parent | Existing Obsidian vault without AI4PKM — likely fresh install candidate |
| Nothing | Anywhere | Empty/new directory — fresh install candidate |
4. If ambiguous, ask user to confirm the vault root path
5. **Warning**: If CWD is inside the `jykim/ai4pkm-vault` template repo itself (check for `.git/` remote pointing to `jykim/ai4pkm-vault`), warn the user — they probably want to operate in their own vault, not the template
### Step 1: Mode Detection
After confirming the vault root, determine which flow to use.
**Decision tree**:
- **Fresh Install**: No `orchestrator.yaml` AND no `_Settings_/` folder → run Fresh Install Flow
- **Upgrade**: `orchestrator.yaml` exists, version < `0.0.30` → run existing epoch-based migration
- **Up-to-date**: `orchestrator.yaml` exists, version == `0.0.30` → verify only, suggest `vault-update` for latest file content
**For Upgrade mode**, read `orchestrator.yaml` to determine the vault's current version.
**Primary signal**: `version` field
- `"1.0"` → original template (pre-epoch 1)
- `"0.0.13"` through `"0.0.19"` → epoch 1 done, needs epoch 2+
- `"0.0.20"` through `"0.0.25"` → epochs 1-2 done, needs epoch 3
- `"0.0.26"` through `"0.0.30"` → fully up to date
**Fallback signals** (if `version` is missing or `"1.0"`):
| Signal | Indicates |
|--------|-----------|
| `.gobi/` directory exists | At least partial epoch 1 |
| `BRAIN.md` exists | At least partial epoch 1 |
| `VAULTS.md` exists | At least partial epoch 1 |
| EDM/GDR/TIU/ACB nodes in orchestrator | Epoch 1 complete |
| `captures_dir` in orchestrator | Epoch 2+ |
| `capture_prompt_path` in orchestrator | Epoch 3 |
| Prompts: DDO, ICB, DRB exist | Epoch 1 complete |
| Prompts: PBU exists | Epoch 2 complete |
| Bases: Participants, Publish, Skills exist | Epoch 2 complete |
### Step 2: Backup (Conditional)
**Fresh Install**: Skip backup — nothing to back up. Offer `git init` if the user wants version control from the start (this happens at the end of the fresh install flow).
**Upgrade**: This step is mandatory — migration must not proceed without user confirming their backup choice.
Present the following to the user:
```
마이그레이션을 시작하기 전에 백업을 권장합니다. 어떤 방식을 선호하시나요?
1. Git 리포지토리 초기화 (git init + initial commit) — 변경 이력 추적 가능
2. 압축 파일로 백업 (zip) — 간단한 스냅샷
3. 이미 백업했으므로 건너뛰기
```
**Action by choice**:
1. **Git backup**:
- If `.git/` already exists → create a pre-migration commit: `git add -A && git commit -m "Pre-migration backup"`
- If no `.git/` → `git init && git add -A && git commit -m "Initial commit (pre-migration backup)"`
2. **Zip backup**:
- Create `{vault_name}_backup_{timestamp}.zip` in the **parent directory** of the vault
```bash
cd .. && zip -r "{vault_name}_backup_$(date +%Y%m%d_%H%M%S).zip" "{vault_name}/" && cd "{vault_name}"
```
3. **Skip** — user confirms they already have a backup
### Step 3: Generate Plan & Confirm
**Fresh Install**: Show a summary of what will be created (directories, config files, prompts, skills) and ask for confirmation.
**Upgrade**: Based on detected version, determine which epochs apply. For each epoch, check every step's precondition and mark:
- ✅ Already done (precondition met)
- ⬜ TODO (needs to be applied)
Present the plan to the user. User can:
- Approve all
- Select specific epochs (upgrade only)
- Skip individual steps
### Step 4: Execute
**Fresh Install** → run the Fresh Install Flow (see below)
**Upgrade** → apply changes epoch by epoch, step by step. Back up any modified files. Track progress in `.gobi/migrations.yaml`.
### Step 5: Verify
Run the verification checklist to confirm everything is correct.
### Step 6: Auto-invoke gobi-onboarding
After verification completes, automatically hand off to gobi-onboarding.
**Fresh install** → always full onboarding (BRAIN.md is a placeholder template):
```
마이그레이션이 완료됐어요! 이제 온보딩을 시작할게요.
```
→ Read `_Settings_/Skills/gobi-onboarding/SKILL.md` and begin full onboarding flow
**Upgrade** → route based on BRAIN.md state:
```
1. Check if BRAIN.md exists
├── No → "BRAIN.md가 없어요. 온보딩을 통해 프로필을 만들어볼까요?"
│ → Read gobi-onboarding SKILL.md, invoke full flow
└── Yes → Read BRAIN.md content
├── Template/placeholder (<100 words real content)
│ → "마이그레이션이 완료됐어요! 프로필이 아직 기본 템플릿이에요. 온보딩을 시작할게요."
│ → Read gobi-onboarding SKILL.md, invoke Step 4 (Community Onboarding)
└── Rich content (>100 words, personalized)
→ Check publish status (two-layer approach):
1. Read vaultSlug from .gobi/settings.yaml
└── If vaultSlug missing → "먼저 gobi init으로 볼트를 연결해주세요." → Suggest: gobi init
2. Primary: `gobi --json brain list-updates --mine --limit 1`
└── If data array non-empty → Already published (confirmed)
3. Fallback: `gobi --json brain search --query {vaultSlug}`
└── Parse JSON; check if any item in data has vaultSlug EXACTLY matching
├── Already published (either check confirms)
│ → "마이그레이션이 완료됐어요! 프로필이 이미 커뮤니티에 공유돼 있어요."
│ → Suggest: gobi brain post-update (share what's new)
└── Not yet published (both checks negative)
→ "마이그레이션이 완료됐어요! 프로필이 잘 갖춰져 있어요. 커뮤니티에 공유해볼까요?"
→ Suggest: gobi brain publish
```
---
## Fresh Install Flow
*Creates a complete AI4PKM vault from scratch using the latest template files from GitHub.*
### FI-1: Scaffold Directories
Create the full directory structure:
```bash
mkdir -p _Settings_/{Prompts,Bases,Templates,Skills,Tasks,Guidelines,History,History/Ambient,History/Capture,Logs}
mkdir -p AI/{Analysis,Briefing,Canvas,Roundup,Summary,Writeup}
mkdir -p Ingest/{Clippings,Documents}
mkdir -p Journal
mkdir -p Topics
mkdir -p _Outbox_/BrainUpdates
mkdir -p .gobi
mkdir -p .claude
```
### FI-2: Fetch Root Config Files
Fetch these files from the template repo into the vault root:
```bash
# Root configuration files
for file in orchestrator.yaml AGENTS.md CLAUDE.md GEMINI.md BRAIN.md BRAIN_PROMPT.md VAULTS.md README.md .gitignore; do
gh api "repos/jykim/ai4pkm-vault/contents/${file}?ref=main" -q '.content' | base64 -d > "${file}"
done
```
**Conflict handling**: If any file already exists:
- Identical to template → skip silently
- Differs from template → ask user: overwrite / skip / merge
- `orchestrator.yaml` → always use merge logic (see Orchestrator Merge Rules)
- `.gobi/settings.yaml` → never overwrite, only add missing keys
### FI-3: Fetch .gobi/ Config
```bash
# settings.yaml
gh api "repos/jykim/ai4pkm-vault/contents/.gobi/settings.yaml?ref=main" -q '.content' | base64 -d > .gobi/settings.yaml
# syncfiles
gh api "repos/jykim/ai4pkm-vault/contents/.gobi/syncfiles?ref=main" -q '.content' | base64 -d > .gobi/syncfiles
```
After creating `settings.yaml`, update user-specific values:
- `claudePath` — set via: `which claude` (or user's actual path)
- `vaultSlug` — will be set by `gobi init` during onboarding
**If `.gobi/settings.yaml` already exists**: Preserve as-is, only add missing keys by merging.
### FI-4: Fetch Prompts, Bases, Templates
Use `gh api` directory listing to discover files dynamically (forward-compatible with new files added to the template):
```bash
# Fetch all prompts (use while-read to handle filenames with spaces)
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Prompts?ref=main" -q '.[].name' | while IFS= read -r file; do
encoded=$(echo "$file" | sed 's/ /%20/g')
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Prompts/${encoded}?ref=main" -q '.content' | base64 -d > "_Settings_/Prompts/${file}"
done
# Fetch all bases
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Bases?ref=main" -q '.[].name' | while IFS= read -r file; do
encoded=$(echo "$file" | sed 's/ /%20/g')
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Bases/${encoded}?ref=main" -q '.content' | base64 -d > "_Settings_/Bases/${file}"
done
# Fetch all templates
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Templates?ref=main" -q '.[].name' | while IFS= read -r file; do
encoded=$(echo "$file" | sed 's/ /%20/g')
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Templates/${encoded}?ref=main" -q '.content' | base64 -d > "_Settings_/Templates/${file}"
done
```
### FI-5: Fetch Skills (Recursive)
Skills are organized in subdirectories. List each skill directory, then fetch its files:
```bash
# List skill directories (use while-read to handle names with spaces)
gh api "repos/jykim/ai4pkm-vault/contents/_Settings_/Skills?ref=main" -q '.[] | select(.type=="dir") | .name' | while IFS= read -r skill_dir; do
mkdir -p "_Settings_/Skills/${skill_dir}"
GitHubで見る