7913116a8e
- .claude/agents/fn-analizador/SKILL.md - .claude/agents/fn-constructor/SKILL.md - .claude/agents/fn-executor/SKILL.md - .claude/agents/fn-mejorador/SKILL.md - .claude/agents/fn-orquestador/SKILL.md - .claude/agents/fn-recopilador/SKILL.md - .claude/commands/app.md - .claude/commands/compile.md - .claude/commands/cpp-app.md - .claude/commands/create_functions.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
105 lines
3.0 KiB
Bash
105 lines
3.0 KiB
Bash
#!/usr/bin/env bash
|
|
# keepass_to_pass
|
|
# ---------------
|
|
# Pipeline: exporta entries del KeePassXC database a `pass`.
|
|
#
|
|
# Cada entry queda en pass como multilinea:
|
|
# <password>
|
|
# user: <username>
|
|
# url: <url>
|
|
# notes: <notes>
|
|
#
|
|
# Path en pass: <prefix>/<keepass_path>. Espacios reemplazados por `_`.
|
|
#
|
|
# REQUIERE:
|
|
# - keepassxc-cli, pass, jq
|
|
# - KEEPASS_DB (env)
|
|
# - master password en pass meta/keepassxc-master o env KEEPASS_PASSWORD
|
|
#
|
|
# USO:
|
|
# ./fn run keepass_to_pass [--prefix keepass] [--overwrite] [--dry-run]
|
|
#
|
|
# FLAGS:
|
|
# --prefix <p> Prefijo en pass (default: keepass)
|
|
# --overwrite Sobreescribe entradas existentes en pass
|
|
# --dry-run No escribe; solo lista lo que haria
|
|
|
|
set -euo pipefail
|
|
|
|
REGISTRY_ROOT="${FN_REGISTRY_ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)}"
|
|
|
|
# shellcheck disable=SC1091
|
|
source "$REGISTRY_ROOT/bash/functions/infra/keepass_dump.sh"
|
|
# shellcheck disable=SC1091
|
|
source "$REGISTRY_ROOT/bash/functions/infra/pass_set.sh"
|
|
|
|
prefix="keepass"
|
|
overwrite=0
|
|
dry_run=0
|
|
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
--prefix) prefix="$2"; shift 2 ;;
|
|
--overwrite) overwrite=1; shift ;;
|
|
--dry-run) dry_run=1; shift ;;
|
|
-h|--help)
|
|
grep '^#' "$0" | sed 's/^# \?//'
|
|
exit 0 ;;
|
|
*) echo "keepass_to_pass: flag desconocido: $1" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
echo "==> Dumping KeePassXC database..."
|
|
dump=$(keepass_dump)
|
|
total=$(printf '%s' "$dump" | jq 'length')
|
|
echo "==> Found $total entries"
|
|
|
|
imported=0
|
|
skipped=0
|
|
empty=0
|
|
i=0
|
|
|
|
while IFS= read -r entry; do
|
|
i=$((i+1))
|
|
path=$(printf '%s' "$entry" | jq -r '.path')
|
|
password=$(printf '%s' "$entry" | jq -r '.password')
|
|
username=$(printf '%s' "$entry" | jq -r '.username')
|
|
url=$(printf '%s' "$entry" | jq -r '.url')
|
|
notes=$(printf '%s' "$entry" | jq -r '.notes')
|
|
|
|
if [ -z "$path" ] || [ "$path" = "null" ]; then
|
|
empty=$((empty+1))
|
|
continue
|
|
fi
|
|
if [ -z "$password" ] || [ "$password" = "null" ]; then
|
|
empty=$((empty+1))
|
|
continue
|
|
fi
|
|
|
|
pass_path="$prefix/$path"
|
|
|
|
if [ "$overwrite" -eq 0 ] && [ -f "${PASSWORD_STORE_DIR:-$HOME/.password-store}/$pass_path.gpg" ]; then
|
|
skipped=$((skipped+1))
|
|
printf '[%d/%d] SKIP %s (existe)\n' "$i" "$total" "$pass_path"
|
|
continue
|
|
fi
|
|
|
|
multiline="$password"
|
|
[ -n "$username" ] && [ "$username" != "null" ] && multiline+=$'\nuser: '"$username"
|
|
[ -n "$url" ] && [ "$url" != "null" ] && multiline+=$'\nurl: '"$url"
|
|
[ -n "$notes" ] && [ "$notes" != "null" ] && multiline+=$'\nnotes: '"$notes"
|
|
|
|
if [ "$dry_run" -eq 1 ]; then
|
|
printf '[%d/%d] DRY %s\n' "$i" "$total" "$pass_path"
|
|
else
|
|
if pass_set "$pass_path" "$multiline"; then
|
|
imported=$((imported+1))
|
|
printf '[%d/%d] IMPORT %s\n' "$i" "$total" "$pass_path"
|
|
else
|
|
printf '[%d/%d] FAIL %s\n' "$i" "$total" "$pass_path" >&2
|
|
fi
|
|
fi
|
|
done < <(printf '%s' "$dump" | jq -c '.[]')
|
|
|
|
echo "==> Done: imported=$imported skipped=$skipped empty=$empty total=$total"
|