Initial commit

This commit is contained in:
Henner M. Kruse
2026-08-04 00:14:42 +02:00
commit c774df7ad7
12 changed files with 705 additions and 0 deletions
+59
View File
@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# Full-text search strictly confined to a configured vault.
#
# Usage: vault_search.sh <query> [vault-name] [subfolder]
# - query: search term (plain text, treated as a fixed string, not a
# shell-interpreted pattern)
# - vault-name: optional if only one vault is configured
# - subfolder: optional, relative subfolder to narrow the search; rejected
# if it tries to escape the vault (e.g. contains '..' or is
# an absolute path)
#
# The vault path always comes from
# ~/.agent-skills/obsidian-vault-kb/config.json — never from a raw argument —
# so this script can't be used to search outside the configured vault(s).
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=_lib.sh
source "$SCRIPT_DIR/_lib.sh"
QUERY="${1:?Usage: vault_search.sh <query> [vault-name] [subfolder]}"
VAULT_NAME="${2:-}"
SUBFOLDER="${3:-}"
VAULT_RAW="$(resolve_vault_path "$VAULT_NAME")"
VAULT="$(canonicalize_and_check_dir "$VAULT_RAW")"
SEARCH_ROOT="$VAULT"
if [ -n "$SUBFOLDER" ]; then
case "$SUBFOLDER" in
/*|*..*)
echo "Error: subfolder must be a relative path within the vault (no '..' or absolute paths)." >&2
exit 1
;;
esac
CANDIDATE="$VAULT/$SUBFOLDER"
SEARCH_ROOT="$(realpath -e "$CANDIDATE" 2>/dev/null)" || {
echo "Error: subfolder '$SUBFOLDER' does not exist in the vault." >&2
exit 1
}
# Ensure the resolved path is still inside the vault after symlink resolution.
case "$SEARCH_ROOT" in
"$VAULT"/*|"$VAULT") ;;
*)
echo "Error: subfolder resolves outside the vault, refusing." >&2
exit 1
;;
esac
fi
echo "== Search root: $SEARCH_ROOT =="
echo
if command -v rg >/dev/null 2>&1; then
rg -i -n --fixed-strings -- "$QUERY" "$SEARCH_ROOT" \
-g '!.obsidian' -g '!.git' -g '*.md' || echo "(no matches)"
else
grep -ril -- "$QUERY" "$SEARCH_ROOT" --include='*.md' 2>/dev/null || echo "(no matches)"
fi