|
| 1 | +#!/usr/bin/env bash |
| 2 | +# ============================================================================= |
| 3 | +# adapters/pi/adapter.sh - Pi Coding Agent platform adapter |
| 4 | +# ============================================================================= |
| 5 | +# Pi loads prompt templates from .pi/prompts/ and skills from |
| 6 | +# .pi/skills/<name>/SKILL.md. This adapter emits a Pi package under dist/pi/ |
| 7 | +# that can be installed with: |
| 8 | +# pi install ./dist/pi |
| 9 | +# or copied into a vault root: |
| 10 | +# cp -R dist/pi/.pi/ /path/to/your/vault/ |
| 11 | +# ============================================================================= |
| 12 | + |
| 13 | +PI_PLATFORM="pi" |
| 14 | +PI_DIR="pi" |
| 15 | + |
| 16 | +adapter_build() { |
| 17 | + local src="$1" dst="$2" |
| 18 | + |
| 19 | + _pi_emit_package_json "$src" "$dst" |
| 20 | + _pi_emit_prompts "$src/commands" "$dst/.pi/prompts" |
| 21 | + _pi_emit_skill "$src" "$dst/.pi/skills/obsidian-second-brain" |
| 22 | + _pi_copy_references "$src/references" "$dst/.pi/skills/obsidian-second-brain/references" |
| 23 | + _pi_copy_scripts "$src/scripts" "$dst/.pi/skills/obsidian-second-brain/scripts" |
| 24 | + _pi_emit_install_hint "$dst" |
| 25 | +} |
| 26 | + |
| 27 | +_pi_emit_package_json() { |
| 28 | + local src="$1" dst="$2" |
| 29 | + local version |
| 30 | + version="$(grep -m1 '^version' "$src/pyproject.toml" 2>/dev/null | sed 's/.*=[[:space:]]*"//; s/".*//')" |
| 31 | + [[ -n "$version" ]] || version="0.0.0" |
| 32 | + |
| 33 | + mkdir -p "$dst" |
| 34 | + cat > "$dst/package.json" <<EOF |
| 35 | +{ |
| 36 | + "name": "obsidian-second-brain-pi", |
| 37 | + "version": "${version}", |
| 38 | + "description": "Pi package for obsidian-second-brain: prompt templates and skill to operate an Obsidian vault as a self-rewriting second brain.", |
| 39 | + "keywords": ["pi-package", "obsidian", "second-brain", "pkm"], |
| 40 | + "license": "MIT", |
| 41 | + "author": "Eugeniu Ghelbur", |
| 42 | + "repository": { |
| 43 | + "type": "git", |
| 44 | + "url": "https://github.com/eugeniughelbur/obsidian-second-brain.git" |
| 45 | + }, |
| 46 | + "pi": { |
| 47 | + "prompts": [".pi/prompts"], |
| 48 | + "skills": [".pi/skills"] |
| 49 | + } |
| 50 | +} |
| 51 | +EOF |
| 52 | +} |
| 53 | + |
| 54 | +_pi_emit_prompts() { |
| 55 | + local src="$1" dst="$2" |
| 56 | + [[ -d "$src" ]] || return 0 |
| 57 | + mkdir -p "$dst" |
| 58 | + |
| 59 | + local f name desc out |
| 60 | + for f in "$src"/*.md; do |
| 61 | + [[ -f "$f" ]] || continue |
| 62 | + should_include "$f" "$PI_PLATFORM" || continue |
| 63 | + |
| 64 | + name="$(basename "$f" .md)" |
| 65 | + desc="$(parse_frontmatter "$f" description)" |
| 66 | + [[ -z "$desc" ]] && desc="Run the /$name command of the obsidian-second-brain skill." |
| 67 | + desc="${desc#\"}"; desc="${desc%\"}" |
| 68 | + |
| 69 | + out="$dst/$name.md" |
| 70 | + { |
| 71 | + echo "---" |
| 72 | + printf 'description: "%s"\n' "${desc//\"/\\\"}" |
| 73 | + if _pi_command_takes_args "$f"; then |
| 74 | + printf 'argument-hint: "[args]"\n' |
| 75 | + fi |
| 76 | + echo "---" |
| 77 | + echo |
| 78 | + echo "Run the obsidian-second-brain /$name command:" |
| 79 | + echo |
| 80 | + command_body "$f" |
| 81 | + } > "$out" |
| 82 | + |
| 83 | + _pi_rewrite_paths_for_prompt "$out" |
| 84 | + rewrite_tool_neutral "$out" |
| 85 | + done |
| 86 | +} |
| 87 | + |
| 88 | +_pi_command_takes_args() { |
| 89 | + local file="$1" |
| 90 | + command_body "$file" | grep -qE '<[^>]+>' \ |
| 91 | + || parse_frontmatter "$file" description | grep -qE '<[^>]+>' |
| 92 | +} |
| 93 | + |
| 94 | +_pi_rewrite_paths_for_prompt() { |
| 95 | + local file="$1" |
| 96 | + [[ -f "$file" ]] || return 0 |
| 97 | + perl -i -pe ' |
| 98 | + s|~/.claude/skills/obsidian-second-brain/|.pi/skills/obsidian-second-brain/|g; |
| 99 | + s~(^|[^A-Za-z0-9_./-])\.?/?references/~$1.pi/skills/obsidian-second-brain/references/~g; |
| 100 | + s~(^|[^A-Za-z0-9_./-])\.?/?scripts/(?!build\.sh)~$1.pi/skills/obsidian-second-brain/scripts/~g; |
| 101 | + ' "$file" |
| 102 | +} |
| 103 | + |
| 104 | +_pi_emit_skill() { |
| 105 | + local src="$1" dst="$2" |
| 106 | + mkdir -p "$dst" |
| 107 | + local out="$dst/SKILL.md" |
| 108 | + |
| 109 | + { |
| 110 | + cat <<'EOF' |
| 111 | +--- |
| 112 | +name: obsidian-second-brain |
| 113 | +description: > |
| 114 | + Operate any Obsidian vault as a living, self-rewriting second brain. |
| 115 | + Use this skill when the user asks to save, search, update, or manage their |
| 116 | + Obsidian vault, or when they invoke any /obsidian-* or /research command. |
| 117 | +--- |
| 118 | +
|
| 119 | +# Obsidian Second Brain - Pi Operating Manual |
| 120 | +
|
| 121 | +This vault can run the **obsidian-second-brain** skill. The skill ships prompt |
| 122 | +templates under `.pi/prompts/` (type `/obsidian-save`, `/obsidian-daily`, etc.) |
| 123 | +and this discovery skill (`/skill:obsidian-second-brain`). |
| 124 | +
|
| 125 | +## How to operate |
| 126 | +
|
| 127 | +1. Read `_CLAUDE.md` in the vault root, if it exists, to learn the user's vault |
| 128 | + conventions. |
| 129 | +2. When the user types a prompt template like `/obsidian-save`, follow its |
| 130 | + instructions step by step. |
| 131 | +3. Treat the AI-first vault rule |
| 132 | + (`./references/ai-first-rules.md`) as non-negotiable for every note you |
| 133 | + write: `## For future Claude` preamble, rich frontmatter |
| 134 | + (`type`, `date`, `tags`, `ai-first: true`), `[[wikilinks]]` for every |
| 135 | + person/project/concept, recency markers per external claim, sources verbatim, |
| 136 | + confidence levels where applicable. |
| 137 | +4. If `_CLAUDE.md` is missing, run `/obsidian-init` to generate it. |
| 138 | +
|
| 139 | +## Command routing table |
| 140 | +EOF |
| 141 | + |
| 142 | + emit_routing_table_grouped "$src/commands" "$PI_PLATFORM" ".pi/prompts" |
| 143 | + emit_trigger_reference "$src/commands" "$PI_PLATFORM" |
| 144 | + |
| 145 | + cat <<'EOF' |
| 146 | +
|
| 147 | +--- |
| 148 | +
|
| 149 | +*Generated by adapters/pi/adapter.sh - do not edit manually.* |
| 150 | +EOF |
| 151 | + } > "$out" |
| 152 | + |
| 153 | + rewrite_tool_neutral "$out" |
| 154 | + perl -i -pe ' |
| 155 | + s|~/.claude/skills/obsidian-second-brain/||g; |
| 156 | + s|\.pi/skills/obsidian-second-brain/||g; |
| 157 | + s~(^|[^A-Za-z0-9_./-])\.?/?references/~$1./references/~g; |
| 158 | + s~(^|[^A-Za-z0-9_./-])\.?/?scripts/(?!build\.sh)~$1./scripts/~g; |
| 159 | + ' "$out" |
| 160 | +} |
| 161 | + |
| 162 | +_pi_copy_references() { |
| 163 | + local src="$1" dst="$2" |
| 164 | + [[ -d "$src" ]] || return 0 |
| 165 | + mkdir -p "$dst" |
| 166 | + cp -R "$src/." "$dst/" |
| 167 | + find "$dst" -type f -name '*.md' -print0 | while IFS= read -r -d '' f; do |
| 168 | + rewrite_tool_neutral "$f" |
| 169 | + rewrite_platform_paths "$f" "$PI_DIR" |
| 170 | + done |
| 171 | +} |
| 172 | + |
| 173 | +_pi_copy_scripts() { |
| 174 | + local src="$1" dst="$2" |
| 175 | + [[ -d "$src" ]] || return 0 |
| 176 | + mkdir -p "$dst" |
| 177 | + cp -R "$src/." "$dst/" |
| 178 | +} |
| 179 | + |
| 180 | +_pi_emit_install_hint() { |
| 181 | + local dst="$1" |
| 182 | + cat > "$dst/INSTALL.md" <<'EOF' |
| 183 | +# Install on Pi |
| 184 | +
|
| 185 | +Build the Pi package from the repo: |
| 186 | +
|
| 187 | +```bash |
| 188 | +git clone https://github.com/eugeniughelbur/obsidian-second-brain.git |
| 189 | +cd obsidian-second-brain |
| 190 | +bash scripts/build.sh --platform pi |
| 191 | +``` |
| 192 | +
|
| 193 | +Then either install the package into Pi: |
| 194 | +
|
| 195 | +```bash |
| 196 | +pi install ./dist/pi |
| 197 | +``` |
| 198 | +
|
| 199 | +Or copy the built `.pi/` tree into your vault so Pi discovers the prompt |
| 200 | +templates and skill from the project root: |
| 201 | +
|
| 202 | +```bash |
| 203 | +cp -R dist/pi/.pi/ /path/to/your/vault/ |
| 204 | +``` |
| 205 | +
|
| 206 | +Then start Pi from your vault root. The `/obsidian-*` and `/research` prompt |
| 207 | +templates will be available, and the discovery skill loads via |
| 208 | +`/skill:obsidian-second-brain`. |
| 209 | +
|
| 210 | +## Research toolkit |
| 211 | +
|
| 212 | +The research commands (`/research`, `/research-deep`, `/x-read`, `/x-pulse`, |
| 213 | +`/youtube`, `/notebooklm`, `/podcast`) need the same API keys as the other |
| 214 | +platforms. Copy `.env.example` to `~/.config/obsidian-second-brain/.env`, set |
| 215 | +permissions to `600`, and paste in the required keys. Pi reads those same |
| 216 | +environment variables, or you can export them before running Pi. |
| 217 | +
|
| 218 | +## Background agents |
| 219 | +
|
| 220 | +Pi has no background-bash or PostCompact-hook equivalent. Run `/obsidian-nightly` |
| 221 | +manually or schedule it with cron outside of Pi. |
| 222 | +EOF |
| 223 | +} |
0 commit comments