Fixed setups

This commit is contained in:
Henner M. Kruse
2026-08-04 11:15:24 +02:00
parent e485d33f00
commit 6c6fc35a1f
9 changed files with 609 additions and 288 deletions
+173
View File
@@ -0,0 +1,173 @@
#!/usr/bin/env bash
# One-shot setup for the obsidian-vault-kb plugin.
#
# Order matters here, deliberately: the permission rules are established
# FIRST, against a stable path we control ourselves
# (~/.agent-skills/obsidian-vault-kb/bin/), not against Claude Code's
# internal plugin cache path (which changes on every plugin update).
# Configuration (vaults, mode) comes after. Re-running this script after a
# plugin update re-syncs the stable copy without the permission rules ever
# needing to change again.
#
# Usage:
# setup.sh --settings-scope (project|user) [--project-dir <path>]
# --mode (read-only|append|maintain)
# --vault <name>=<path> [--vault <name>=<path> ...]
#
# Prints a JSON summary of what changed to stdout at the end.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PLUGIN_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
SKILL_DIR="$(realpath "$PLUGIN_DIR/skills/obsidian-vault-kb")"
if ! command -v python3 >/dev/null 2>&1; then
echo "Error: python3 is required." >&2
exit 1
fi
# --- 1. Stable, self-controlled target location. Copy the three wrapper
# scripts and their shared helper there — this is the ONLY location
# permissions will ever point to. ---
STABLE_DIR="$HOME/.agent-skills/obsidian-vault-kb/bin"
mkdir -p "$STABLE_DIR"
for f in vault_index.sh vault_search.sh vault_backlinks.sh _lib.sh; do
cp "$SKILL_DIR/scripts/$f" "$STABLE_DIR/$f"
done
chmod +x "$STABLE_DIR/vault_index.sh" "$STABLE_DIR/vault_search.sh" "$STABLE_DIR/vault_backlinks.sh"
# Tilde-form path for permission rules and SKILL.md's example commands —
# Claude Code matches Bash permission rules against the literal,
# unexpanded command text, so a rule written with the resolved absolute
# $HOME path (e.g. /home/hmk/...) does NOT match a command Claude typed as
# "~/...", even though both point at the same file. Keep both sides in
# tilde form so they actually match.
TILDE_STABLE_DIR="~/.agent-skills/obsidian-vault-kb/bin"
TILDE_CONFIG_FILE="~/.agent-skills/obsidian-vault-kb/config.json"
# --- 2. Parse arguments ---
SETTINGS_SCOPE=""
PROJECT_DIR="$PWD"
MODE=""
VAULTS=()
while [ $# -gt 0 ]; do
case "$1" in
--settings-scope) SETTINGS_SCOPE="$2"; shift 2 ;;
--project-dir) PROJECT_DIR="$2"; shift 2 ;;
--mode) MODE="$2"; shift 2 ;;
--vault) VAULTS+=("$2"); shift 2 ;;
*) echo "Error: unknown argument '$1'" >&2; exit 1 ;;
esac
done
if [ "$SETTINGS_SCOPE" != "project" ] && [ "$SETTINGS_SCOPE" != "user" ]; then
echo "Error: --settings-scope must be 'project' or 'user'" >&2
exit 1
fi
case "$MODE" in
read-only|append|maintain) ;;
*) echo "Error: --mode must be read-only, append, or maintain" >&2; exit 1 ;;
esac
if [ "${#VAULTS[@]}" -eq 0 ]; then
echo "Error: at least one --vault <name>=<path> is required" >&2
exit 1
fi
if [ "$SETTINGS_SCOPE" = "project" ]; then
SETTINGS_FILE="$PROJECT_DIR/.claude/settings.json"
else
SETTINGS_FILE="$HOME/.claude/settings.json"
fi
CONFIG_DIR="$HOME/.agent-skills/obsidian-vault-kb"
CONFIG_FILE="$CONFIG_DIR/config.json"
mkdir -p "$CONFIG_DIR"
# --- 3. Write permissions FIRST, against the stable path from step 1 ---
mkdir -p "$(dirname "$SETTINGS_FILE")"
python3 - "$SETTINGS_FILE" "$TILDE_STABLE_DIR" "$TILDE_CONFIG_FILE" << 'PYEOF'
import json, os, sys
settings_file, tilde_stable_dir, tilde_config_file = sys.argv[1:4]
settings = {}
if os.path.exists(settings_file):
with open(settings_file) as f:
settings = json.load(f)
perms = settings.setdefault("permissions", {})
allow = perms.setdefault("allow", [])
new_rules = [
f"Bash({tilde_stable_dir}/vault_index.sh:*)",
f"Bash({tilde_stable_dir}/vault_search.sh:*)",
f"Bash({tilde_stable_dir}/vault_backlinks.sh:*)",
f"Read({tilde_config_file})",
]
for rule in new_rules:
if rule not in allow:
allow.append(rule)
with open(settings_file, "w") as f:
json.dump(settings, f, indent=2)
f.write("\n")
PYEOF
# --- 4. THEN configuration: validate + write/merge vaults and mode ---
VAULTS_JSON=$(python3 -c '
import json, os, sys
pairs = sys.argv[1:]
vaults = []
for p in pairs:
name, path = p.split("=", 1)
real = os.path.realpath(path)
if not os.path.isdir(real):
sys.stderr.write(f"Error: vault path {path!r} (for {name!r}) is not a directory.\n")
sys.exit(1)
vaults.append({"name": name, "path": real})
print(json.dumps(vaults))
' "${VAULTS[@]}")
python3 - "$CONFIG_FILE" "$VAULTS_JSON" "$MODE" << 'PYEOF'
import json, os, sys
config_file, new_vaults_json, mode = sys.argv[1], sys.argv[2], sys.argv[3]
new_vaults = json.loads(new_vaults_json)
existing = {"vaults": [], "mode": mode}
if os.path.exists(config_file):
with open(config_file) as f:
existing = json.load(f)
existing["mode"] = mode
existing_by_name = {v["name"]: v for v in existing.get("vaults", [])}
for v in new_vaults:
existing_by_name[v["name"]] = v # upsert: new/updated path always wins
existing["vaults"] = list(existing_by_name.values())
with open(config_file, "w") as f:
json.dump(existing, f, indent=2)
f.write("\n")
PYEOF
# --- 5. Summary ---
python3 - "$STABLE_DIR" "$SETTINGS_FILE" "$CONFIG_FILE" "$MODE" "$VAULTS_JSON" "$TILDE_STABLE_DIR" "$TILDE_CONFIG_FILE" << 'PYEOF'
import json, sys
stable_dir, settings_file, config_file, mode, vaults_json, tilde_stable_dir, tilde_config_file = sys.argv[1:8]
print(json.dumps({
"stable_script_location": stable_dir,
"settings_file": settings_file,
"config_file": config_file,
"mode": mode,
"vaults_registered": json.loads(vaults_json),
"permission_rules_added": [
f"Bash({tilde_stable_dir}/vault_index.sh:*)",
f"Bash({tilde_stable_dir}/vault_search.sh:*)",
f"Bash({tilde_stable_dir}/vault_backlinks.sh:*)",
f"Read({tilde_config_file})"
],
"note": "The permission rules point at a stable location this script controls (~/.agent-skills/obsidian-vault-kb/bin/), not at Claude Code's internal plugin cache — so they survive future plugin updates without changing. They're written in tilde form (~/...) to match the literal, unexpanded command text Claude Code matches against, not the resolved absolute $HOME path. Permissions are written to disk now, but Claude Code loads permissions at session start and does not always pick up changes made by its own file edits within the same session — if a vault script call still prompts after this, start a fresh session rather than re-running setup."
}, indent=2))
PYEOF