#!/bin/bash # # Install Hindsight Memory for OpenAI Codex CLI # # Usage: # curl -fsSL https://hindsight.vectorize.io/get-codex | bash # # Options: # --uninstall Remove Hindsight hooks # --mode Mode: local (default) or cloud # # Examples: # curl -fsSL https://hindsight.vectorize.io/get-codex | bash # curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --mode cloud # curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --uninstall # set -e # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' BOLD='\033[1m' DIM='\033[2m' NC='\033[0m' # No Color print_info() { echo -e "${BLUE}ℹ${NC} $1" } print_success() { echo -e "${GREEN}✓${NC} $1" } print_error() { echo -e "${RED}✗${NC} $1" exit 1 } print_warning() { echo -e "${YELLOW}⚠${NC} $1" } print_step() { echo "" echo -e "${BOLD}${CYAN}▸ $1${NC}" echo "" } print_banner() { echo "" # ANSI logo echo -e " \033[38;2;9;127;184m▄\033[0m\033[48;2;8;130;178m\033[38;2;5;133;186m▄\033[0m \033[48;2;10;143;160m\033[38;2;10;143;165m▄\033[0m\033[38;2;7;140;156m▄\033[0m " echo -e " \033[38;2;8;125;192m▄\033[0m \033[38;2;3;132;191m▀\033[0m\033[38;2;2;133;192m▄\033[0m \033[38;2;3;132;180m▄\033[0m\033[38;2;1;137;184m▄\033[0m\033[38;2;3;133;174m▄\033[0m \033[38;2;3;142;176m▄\033[0m\033[38;2;4;142;169m▀\033[0m \033[38;2;10;144;164m▄\033[0m " echo -e "\033[38;2;6;121;195m▀\033[0m\033[38;2;5;128;203m▀\033[0m\033[48;2;5;124;195m\033[38;2;3;125;200m▄\033[0m\033[38;2;2;126;196m▄\033[0m\033[48;2;3;128;188m\033[38;2;1;131;196m▄\033[0m\033[48;2;0;152;219m\033[38;2;2;131;191m▄\033[0m\033[38;2;1;141;196m▀\033[0m\033[38;2;1;135;183m▀\033[0m\033[38;2;1;148;198m▀\033[0m\033[48;2;1;156;202m\033[38;2;2;135;180m▄\033[0m\033[48;2;4;134;169m\033[38;2;1;137;177m▄\033[0m\033[38;2;3;138;173m▄\033[0m\033[48;2;6;137;165m\033[38;2;2;140;170m▄\033[0m\033[38;2;7;144;169m▀\033[0m\033[38;2;7;139;158m▀\033[0m" echo -e " \033[48;2;2;128;202m\033[38;2;2;124;201m▄\033[0m\033[48;2;1;130;201m\033[38;2;0;135;212m▄\033[0m\033[38;2;2;128;196m▄\033[0m \033[48;2;2;142;204m\033[38;2;7;138;199m▄\033[0m \033[38;2;1;135;186m▄\033[0m\033[48;2;1;142;186m\033[38;2;2;144;194m▄\033[0m\033[48;2;3;138;176m\033[38;2;2;134;176m▄\033[0m " echo -e " \033[48;2;8;118;200m\033[38;2;8;121;209m▄\033[0m\033[38;2;3;121;203m▀\033[0m \033[38;2;3;122;192m▀\033[0m\033[38;2;1;138;216m▀\033[0m\033[48;2;0;138;210m\033[38;2;3;128;198m▄\033[0m\033[48;2;0;126;188m\033[38;2;2;131;198m▄\033[0m\033[48;2;0;142;205m\033[38;2;3;132;193m▄\033[0m\033[38;2;1;140;196m▀\033[0m \033[38;2;4;134;175m▀\033[0m\033[48;2;13;135;167m\033[38;2;8;136;174m▄\033[0m " echo "" echo -e " ${BOLD}HINDSIGHT FOR CODEX CLI${NC}" echo -e " ${DIM}Give your Codex agent persistent memory${NC}" echo "" } GITHUB_RAW="https://raw.githubusercontent.com/vectorize-io/hindsight/main/hindsight-integrations/codex" INSTALL_DIR="${HOME}/.hindsight/codex" SCRIPTS_DIR="${INSTALL_DIR}/scripts" CODEX_DIR="${HOME}/.codex" HOOKS_FILE="${CODEX_DIR}/hooks.json" CONFIG_FILE="${CODEX_DIR}/config.toml" # Script files to download SCRIPT_FILES=( "scripts/session_start.py" "scripts/recall.py" "scripts/retain.py" "scripts/lib/__init__.py" "scripts/lib/bank.py" "scripts/lib/client.py" "scripts/lib/config.py" "scripts/lib/content.py" "scripts/lib/daemon.py" "scripts/lib/llm.py" "scripts/lib/state.py" ) # Parse arguments MODE="" UNINSTALL=false while [[ $# -gt 0 ]]; do case $1 in --uninstall) UNINSTALL=true shift ;; --mode) MODE="$2" shift 2 ;; --help|-h) echo "Usage: curl -fsSL https://hindsight.vectorize.io/get-codex | bash [-s -- OPTIONS]" echo "" echo "Options:" echo " --mode Mode: local (default) or cloud" echo " --uninstall Remove Hindsight hooks" exit 0 ;; *) print_error "Unknown option: $1" ;; esac done # ────────────────────────────────────────────────────────────────────────────── # Uninstall # ────────────────────────────────────────────────────────────────────────────── if [ "$UNINSTALL" = true ]; then echo "Uninstalling Hindsight Codex integration..." if [ -d "${SCRIPTS_DIR}" ]; then rm -rf "${SCRIPTS_DIR}" echo " Removed ${SCRIPTS_DIR}" fi if [ -f "${HOOKS_FILE}" ]; then rm -f "${HOOKS_FILE}" echo " Removed ${HOOKS_FILE}" fi if [ -f "${CONFIG_FILE}" ]; then sed -i.bak '/^codex_hooks *= *true/d' "${CONFIG_FILE}" && rm -f "${CONFIG_FILE}.bak" echo " Removed codex_hooks from ${CONFIG_FILE}" fi echo "" print_success "Uninstall complete." exit 0 fi # ────────────────────────────────────────────────────────────────────────────── # Install # ────────────────────────────────────────────────────────────────────────────── print_banner # Step 1: Check prerequisites print_step "Checking prerequisites" if ! command -v python3 &> /dev/null; then print_error "Python 3 is required.\nInstall from https://python.org" fi print_success "Python 3 available" if ! command -v curl &> /dev/null && ! command -v wget &> /dev/null; then print_error "curl or wget is required to download scripts." fi # Step 2: Select mode if [ -z "$MODE" ]; then if [ -t 0 ] || [ -e /dev/tty ]; then echo -e "${DIM}Select deployment mode:${NC}" echo "" echo -e " ${BOLD}1)${NC} Local ${DIM}- Run Hindsight on your machine (default)${NC}" echo -e " ${BOLD}2)${NC} Cloud ${DIM}- Connect to Hindsight Cloud${NC}" echo "" if [ -t 0 ]; then read -p "Enter choice [1]: " mode_choice else read -p "Enter choice [1]: " mode_choice /dev/null; then curl -fsSL "$url" -o "$dest" else wget -q "$url" -O "$dest" fi } for file in "${SCRIPT_FILES[@]}"; do download_file "${GITHUB_RAW}/${file}" "${SCRIPTS_DIR}/${file#scripts/}" done chmod +x "${SCRIPTS_DIR}/session_start.py" chmod +x "${SCRIPTS_DIR}/recall.py" chmod +x "${SCRIPTS_DIR}/retain.py" print_success "Scripts installed to ${SCRIPTS_DIR}" # Step 4: Download default settings (don't overwrite existing, but update version) SETTINGS_DST="${INSTALL_DIR}/settings.json" if [ ! -f "${SETTINGS_DST}" ]; then download_file "${GITHUB_RAW}/settings.json" "${SETTINGS_DST}" print_success "Default settings written to ${SETTINGS_DST}" else # Merge version and any new keys from upstream into existing settings SETTINGS_TMP="${INSTALL_DIR}/settings.json.new" download_file "${GITHUB_RAW}/settings.json" "${SETTINGS_TMP}" if command -v python3 &> /dev/null; then python3 -c " import json, sys with open('${SETTINGS_DST}') as f: existing = json.load(f) with open('${SETTINGS_TMP}') as f: upstream = json.load(f) # Add new keys from upstream (don't overwrite user customizations) for key, value in upstream.items(): if key not in existing: existing[key] = value # Always update version existing['version'] = upstream.get('version', existing.get('version', '')) with open('${SETTINGS_DST}', 'w') as f: json.dump(existing, f, indent=2) f.write('\n') " 2>/dev/null && { rm -f "${SETTINGS_TMP}" NEW_VER=$(python3 -c "import json; print(json.load(open('${SETTINGS_DST}'))['version'])" 2>/dev/null) print_success "Settings updated (v${NEW_VER}), user customizations preserved" } || { rm -f "${SETTINGS_TMP}" print_info "Keeping existing settings at ${SETTINGS_DST}" } else rm -f "${SETTINGS_TMP}" print_info "Keeping existing settings at ${SETTINGS_DST}" fi fi # Step 5: Configure connection if [ "$MODE" = "cloud" ]; then print_step "Configuring Hindsight Cloud connection" DEFAULT_CLOUD_URL="https://api.hindsight.vectorize.io" echo -e "${DIM}Enter your Hindsight Cloud connection details.${NC}" echo -e "${DIM}Get these from https://ui.hindsight.vectorize.io${NC}" echo "" if [ -t 0 ]; then read -p "Cloud API URL [$DEFAULT_CLOUD_URL]: " CLOUD_URL read -p "API Token: " CLOUD_TOKEN else read -p "Cloud API URL [$DEFAULT_CLOUD_URL]: " CLOUD_URL "$USER_CONFIG" < "${HOOKS_FILE}" </dev/null; then if ! grep -q '^codex_hooks' "${CONFIG_FILE}"; then sed -i.bak '/^\[features\]/a codex_hooks = true' "${CONFIG_FILE}" && rm -f "${CONFIG_FILE}.bak" print_success "Added codex_hooks = true to ${CONFIG_FILE}" else print_info "codex_hooks already enabled" fi else printf '\n[features]\ncodex_hooks = true\n' >> "${CONFIG_FILE}" print_success "Added codex_hooks = true to ${CONFIG_FILE}" fi # Done! echo "" echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo -e "${GREEN} ✓ Installation Complete!${NC}" echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" echo "" echo -e " Hindsight memory is now active in ${BOLD}Codex CLI${NC}." echo "" echo -e " ${DIM}Configuration:${NC}" echo -e " ${CYAN}~/.hindsight/codex/settings.json${NC} ${DIM}(plugin defaults)${NC}" echo -e " ${CYAN}~/.hindsight/codex.json${NC} ${DIM}(personal overrides)${NC}" echo "" echo -e " ${DIM}Start a new Codex session to activate.${NC}" echo "" echo -e " ${DIM}Uninstall:${NC}" echo -e " ${CYAN}curl -fsSL https://hindsight.vectorize.io/get-codex | bash -s -- --uninstall${NC}" echo "" echo -e " ${DIM}Documentation:${NC} ${BLUE}https://hindsight.vectorize.io/sdks/integrations/codex${NC}" echo ""