feat: initial marketplace (knowledge-curator + venture)

This commit is contained in:
2026-06-02 14:31:42 +02:00
commit 45a4f30939
22 changed files with 1463 additions and 0 deletions
+64
View File
@@ -0,0 +1,64 @@
#!/usr/bin/env bash
# backup-memory.sh — PreToolUse hook for memory write tools.
# Snapshots the memory graph FILE before a write. Debounced so one apply-run
# produces a single backup. Never blocks the tool call (always exits 0).
#
# Config (env, all optional):
# KG_MEMORY_FILE explicit path to the MCP memory server's JSON store
# (falls back to MEMORY_FILE_PATH, the official server's var)
# KG_BACKUP_DIR where backups land (default: ~/.claude/kg-backups)
# KG_BACKUP_DEBOUNCE seconds; skip if a newer backup exists (default: 120)
# KG_BACKUP_KEEP how many backups to retain (default: 20)
#
# Tip: set KG_MEMORY_FILE in your shell / Claude Code env so the hook knows
# which file to copy. Without it the hook logs a notice and exits cleanly.
set -uo pipefail
# Drain stdin (hook receives JSON; we don't need it) so the pipe never blocks.
cat >/dev/null 2>&1 || true
MEM="${KG_MEMORY_FILE:-${MEMORY_FILE_PATH:-}}"
BACKUP_DIR="${KG_BACKUP_DIR:-$HOME/.claude/kg-backups}"
DEBOUNCE="${KG_BACKUP_DEBOUNCE:-120}"
KEEP="${KG_BACKUP_KEEP:-20}"
LOG="$BACKUP_DIR/backup.log"
note() { mkdir -p "$BACKUP_DIR" 2>/dev/null || true; echo "[$(date -Iseconds)] $*" >>"$LOG" 2>/dev/null || true; }
# No file configured or file missing -> notice + clean exit (never block writes).
if [ -z "$MEM" ]; then
note "no KG_MEMORY_FILE/MEMORY_FILE_PATH set; skipping file backup"
exit 0
fi
if [ ! -f "$MEM" ]; then
note "memory file not found at '$MEM'; skipping"
exit 0
fi
mkdir -p "$BACKUP_DIR" 2>/dev/null || { note "cannot create $BACKUP_DIR"; exit 0; }
# Debounce: if the newest existing backup is younger than DEBOUNCE seconds, skip.
newest="$(ls -t "$BACKUP_DIR"/kg-backup-*.json 2>/dev/null | head -n1 || true)"
if [ -n "$newest" ]; then
age=$(( $(date +%s) - $(stat -c %Y "$newest" 2>/dev/null || echo 0) ))
if [ "$age" -lt "$DEBOUNCE" ]; then
note "debounced (last backup ${age}s ago < ${DEBOUNCE}s)"
exit 0
fi
fi
ts="$(date +%Y%m%dT%H%M%S)"
dest="$BACKUP_DIR/kg-backup-$ts.json"
if cp "$MEM" "$dest" 2>/dev/null; then
note "backup ok -> $dest"
else
note "backup FAILED copying $MEM"
exit 0
fi
# Prune: keep only the most recent $KEEP backups.
mapfile -t old < <(ls -t "$BACKUP_DIR"/kg-backup-*.json 2>/dev/null | tail -n +"$((KEEP+1))")
for f in "${old[@]:-}"; do [ -n "$f" ] && rm -f "$f" 2>/dev/null || true; done
exit 0