| #!/usr/bin/env bash
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| set -euo pipefail
|
|
|
| SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
| MNEMOCORE_DIR="$(realpath "$SCRIPT_DIR/..")"
|
| BRIDGE_PY="$SCRIPT_DIR/mnemo_bridge.py"
|
| HOOKS_DIR="$SCRIPT_DIR/claude_code/hooks"
|
|
|
| CLAUDE_SETTINGS="$HOME/.claude/settings.json"
|
| CLAUDE_MCP="$HOME/.claude/mcp.json"
|
|
|
| RED='\033[0;31m'
|
| GREEN='\033[0;32m'
|
| YELLOW='\033[1;33m'
|
| BLUE='\033[0;34m'
|
| NC='\033[0m'
|
|
|
|
|
|
|
| info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
| success() { echo -e "${GREEN}[OK]${NC} $*"; }
|
| warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
|
| error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
|
|
|
| check_python() {
|
| if ! python3 -c "import requests" &>/dev/null; then
|
| warn "Python 'requests' not installed. Installing..."
|
| python3 -m pip install --quiet requests
|
| success "requests installed"
|
| fi
|
| }
|
|
|
| check_mnemocore() {
|
| info "Checking MnemoCore connectivity..."
|
| if python3 "$BRIDGE_PY" health &>/dev/null; then
|
| success "MnemoCore is online"
|
| return 0
|
| else
|
| warn "MnemoCore is not running. Start it first with:"
|
| warn " cd $MNEMOCORE_DIR && uvicorn mnemocore.api.main:app --port 8100"
|
| return 1
|
| fi
|
| }
|
|
|
| merge_json() {
|
|
|
| local target="$1"
|
| local fragment="$2"
|
|
|
| if [[ ! -f "$target" ]]; then
|
| echo '{}' > "$target"
|
| fi
|
|
|
| python3 - <<PYEOF
|
| import json, sys
|
| with open("$target") as f:
|
| existing = json.load(f)
|
| with open("$fragment") as f:
|
| new = json.load(f)
|
| # Deep merge (one level)
|
| for k, v in new.items():
|
| if k.startswith("_"):
|
| continue
|
| if k in existing and isinstance(existing[k], dict) and isinstance(v, dict):
|
| existing[k].update(v)
|
| else:
|
| existing[k] = v
|
| with open("$target", "w") as f:
|
| json.dump(existing, f, indent=2)
|
| print("Merged successfully")
|
| PYEOF
|
| }
|
|
|
|
|
|
|
| setup_claude_code() {
|
| info "Setting up Claude Code integration..."
|
| mkdir -p "$HOME/.claude/mnemo_context"
|
|
|
|
|
| info " Configuring MCP server..."
|
| local mcp_tmp
|
| mcp_tmp="$(mktemp /tmp/mnemo_mcp_XXXXXX.json)"
|
| sed \
|
| -e "s|\${MNEMOCORE_DIR}|$MNEMOCORE_DIR|g" \
|
| -e "s|\${HAIM_API_KEY}|${HAIM_API_KEY:-}|g" \
|
| "$SCRIPT_DIR/claude_code/mcp_config.json" > "$mcp_tmp"
|
|
|
| if [[ ! -f "$CLAUDE_MCP" ]]; then
|
| echo '{"mcpServers": {}}' > "$CLAUDE_MCP"
|
| fi
|
|
|
| python3 - "$CLAUDE_MCP" "$mcp_tmp" <<'PYEOF'
|
| import json, sys
|
| with open(sys.argv[1]) as f:
|
| existing = json.load(f)
|
| with open(sys.argv[2]) as f:
|
| new = json.load(f)
|
| existing.setdefault("mcpServers", {}).update(new.get("mcpServers", {}))
|
| with open(sys.argv[1], "w") as f:
|
| json.dump(existing, f, indent=2)
|
| PYEOF
|
| rm -f "$mcp_tmp"
|
| success " MCP server registered in $CLAUDE_MCP"
|
|
|
|
|
| info " Installing hooks in $CLAUDE_SETTINGS..."
|
| if [[ ! -f "$CLAUDE_SETTINGS" ]]; then
|
| echo '{}' > "$CLAUDE_SETTINGS"
|
| fi
|
|
|
| python3 - "$CLAUDE_SETTINGS" "$HOOKS_DIR" <<PYEOF
|
| import json, sys
|
| settings_path = sys.argv[1]
|
| hooks_dir = sys.argv[2]
|
| with open(settings_path) as f:
|
| settings = json.load(f)
|
|
|
| hooks = settings.setdefault("hooks", {})
|
| pre = hooks.setdefault("PreToolUse", [])
|
| post = hooks.setdefault("PostToolUse", [])
|
|
|
| pre_hook = {
|
| "matcher": ".*",
|
| "hooks": [{"type": "command", "command": f"python3 {hooks_dir}/pre_session_inject.py"}]
|
| }
|
| post_hook = {
|
| "matcher": "Edit|Write|MultiEdit",
|
| "hooks": [{"type": "command", "command": f"python3 {hooks_dir}/post_tool_store.py"}]
|
| }
|
|
|
| # Only add if not already present
|
| pre_cmds = [h["hooks"][0]["command"] for h in pre if h.get("hooks")]
|
| post_cmds = [h["hooks"][0]["command"] for h in post if h.get("hooks")]
|
|
|
| if pre_hook["hooks"][0]["command"] not in pre_cmds:
|
| pre.append(pre_hook)
|
| if post_hook["hooks"][0]["command"] not in post_cmds:
|
| post.append(post_hook)
|
|
|
| with open(settings_path, "w") as f:
|
| json.dump(settings, f, indent=2)
|
| print("Hooks installed")
|
| PYEOF
|
| success " Hooks installed in $CLAUDE_SETTINGS"
|
|
|
|
|
| local clause_md="$MNEMOCORE_DIR/CLAUDE.md"
|
| local snippet="$SCRIPT_DIR/claude_code/CLAUDE_memory_snippet.md"
|
| local marker="# MnemoCore β Persistent Cognitive Memory"
|
| if [[ -f "$clause_md" ]] && grep -qF "$marker" "$clause_md"; then
|
| info " CLAUDE.md already contains MnemoCore memory instructions"
|
| else
|
| echo "" >> "$clause_md"
|
| cat "$snippet" >> "$clause_md"
|
| success " Memory instructions appended to $clause_md"
|
| fi
|
|
|
| success "Claude Code integration complete"
|
| }
|
|
|
|
|
|
|
| setup_gemini() {
|
| info "Setting up Gemini CLI integration..."
|
|
|
|
|
| chmod +x "$SCRIPT_DIR/gemini_cli/gemini_wrap.sh"
|
|
|
|
|
| local gemini_md="$MNEMOCORE_DIR/GEMINI.md"
|
| local snippet="$SCRIPT_DIR/gemini_cli/GEMINI_memory_snippet.md"
|
| local marker="# MnemoCore β Persistent Cognitive Memory"
|
| if [[ -f "$gemini_md" ]] && grep -qF "$marker" "$gemini_md"; then
|
| info " GEMINI.md already contains MnemoCore instructions"
|
| elif [[ -f "$gemini_md" ]]; then
|
| echo "" >> "$gemini_md"
|
| cat "$snippet" >> "$gemini_md"
|
| success " Memory instructions appended to $gemini_md"
|
| else
|
| cp "$snippet" "$gemini_md"
|
| success " Created $gemini_md with memory instructions"
|
| fi
|
|
|
| success "Gemini CLI integration complete"
|
| info " Use: $SCRIPT_DIR/gemini_cli/gemini_wrap.sh [args] instead of 'gemini'"
|
| info " Or alias: alias gemini='$SCRIPT_DIR/gemini_cli/gemini_wrap.sh'"
|
| }
|
|
|
|
|
|
|
| setup_aider() {
|
| info "Setting up Aider integration..."
|
| chmod +x "$SCRIPT_DIR/aider/aider_wrap.sh"
|
|
|
|
|
| local aider_env="$MNEMOCORE_DIR/.aider.env"
|
| cat > "$aider_env" <<EOF
|
| # MnemoCore environment for Aider
|
| export MNEMOCORE_URL="${MNEMOCORE_URL:-http://localhost:8100}"
|
| export HAIM_API_KEY="${HAIM_API_KEY:-}"
|
| export BRIDGE_PY="$BRIDGE_PY"
|
| EOF
|
| success "Aider integration complete"
|
| info " Use: $SCRIPT_DIR/aider/aider_wrap.sh [args] instead of 'aider'"
|
| info " Or alias: alias aider='$SCRIPT_DIR/aider/aider_wrap.sh'"
|
| }
|
|
|
|
|
|
|
| setup_universal() {
|
| chmod +x "$SCRIPT_DIR/universal/context_inject.sh"
|
| chmod +x "$SCRIPT_DIR/universal/store_session.sh"
|
| success "Universal scripts ready"
|
| info " Context: $SCRIPT_DIR/universal/context_inject.sh [query] [top-k]"
|
| info " Store: $SCRIPT_DIR/universal/store_session.sh [text] [tags] [ctx]"
|
| }
|
|
|
|
|
|
|
| echo ""
|
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
|
| echo "β MnemoCore Integration Setup β"
|
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
|
| echo ""
|
|
|
|
|
| check_python
|
| check_mnemocore || true
|
|
|
| DO_ALL=false
|
| DO_CLAUDE=false
|
| DO_GEMINI=false
|
| DO_AIDER=false
|
|
|
| for arg in "$@"; do
|
| case "$arg" in
|
| --all) DO_ALL=true ;;
|
| --claude-code) DO_CLAUDE=true ;;
|
| --gemini) DO_GEMINI=true ;;
|
| --aider) DO_AIDER=true ;;
|
| esac
|
| done
|
|
|
| if ! $DO_ALL && ! $DO_CLAUDE && ! $DO_GEMINI && ! $DO_AIDER; then
|
| echo "Which integrations do you want to enable?"
|
| echo " 1) Claude Code (MCP + hooks + CLAUDE.md)"
|
| echo " 2) Gemini CLI (GEMINI.md + wrapper)"
|
| echo " 3) Aider (wrapper script)"
|
| echo " 4) All of the above"
|
| echo ""
|
| read -rp "Enter choice(s) [e.g. 1 3 or 4]: " CHOICES
|
|
|
| for c in $CHOICES; do
|
| case "$c" in
|
| 1) DO_CLAUDE=true ;;
|
| 2) DO_GEMINI=true ;;
|
| 3) DO_AIDER=true ;;
|
| 4) DO_ALL=true ;;
|
| esac
|
| done
|
| fi
|
|
|
| if $DO_ALL; then
|
| DO_CLAUDE=true; DO_GEMINI=true; DO_AIDER=true
|
| fi
|
|
|
| echo ""
|
| setup_universal
|
|
|
| $DO_CLAUDE && setup_claude_code
|
| $DO_GEMINI && setup_gemini
|
| $DO_AIDER && setup_aider
|
|
|
| echo ""
|
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
|
| echo "β Setup complete! Quick start: β"
|
| echo "β β"
|
| echo "β Test bridge: python3 integrations/mnemo_bridge.py health"
|
| echo "β Get context: integrations/universal/context_inject.sh"
|
| echo "β Store memory: integrations/universal/store_session.sh"
|
| echo "ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ"
|
| echo ""
|
|
|