fleet-memory/hindsight-docs/static/get-codex
Nicolò Boschi ecf16ea1e6
fix(codex): cleanup dead code, add release lifecycle and docs (#753)
* fix(codex): cleanup dead code and add to release lifecycle

- Remove orphaned reflect() method from client.py (leftover from dropped auto-mode)
- Remove dead retainToolCalls config default (never wired through)
- Add codex to release-integration.sh valid integrations
- Add settings.json version fallback to release script
- Add codex CI test job in test.yml
- Add codex to integrations.json registry

* docs(codex): add changelog page and link from integration docs

* feat(codex): add hosted installer script (get-codex)

Add self-contained installer at hindsight.vectorize.io/get-codex that
downloads scripts from GitHub, configures hooks, and supports local/cloud
mode selection — no git clone required.

Update docs and README to use the one-liner install:
  curl -fsSL https://hindsight.vectorize.io/get-codex | bash

* chore(codex): remove install.sh in favor of hosted get-codex

* fix(docs): use /next/ prefix for codex changelog link

* fix(docs): use GitHub link for codex changelog back-link
2026-03-30 11:34:43 +02:00

356 lines
12 KiB
Bash
Executable file
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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> 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> 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/tty
fi
mode_choice=${mode_choice:-1}
case $mode_choice in
1) MODE="local" ;;
2) MODE="cloud" ;;
*) MODE="local" ;;
esac
echo ""
else
MODE="local"
fi
fi
print_info "Mode: ${BOLD}$MODE${NC}"
# Step 3: Download scripts from GitHub
print_step "Downloading hook scripts"
mkdir -p "${SCRIPTS_DIR}/lib"
download_file() {
local url="$1"
local dest="$2"
if command -v curl &> /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)
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
print_info "Keeping existing settings at ${SETTINGS_DST}"
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 </dev/tty
read -p "API Token: " CLOUD_TOKEN </dev/tty
fi
CLOUD_URL=${CLOUD_URL:-$DEFAULT_CLOUD_URL}
if [ -z "$CLOUD_TOKEN" ]; then
print_error "API Token is required for cloud mode"
fi
# Write user config
USER_CONFIG="${HOME}/.hindsight/codex.json"
cat > "$USER_CONFIG" <<CFGEOF
{
"hindsightApiUrl": "${CLOUD_URL}",
"hindsightApiToken": "${CLOUD_TOKEN}"
}
CFGEOF
chmod 600 "$USER_CONFIG"
print_success "Cloud config saved to ${USER_CONFIG}"
else
# Local mode — check for LLM provider
print_step "Checking LLM configuration"
if [ -n "${OPENAI_API_KEY:-}" ]; then
print_success "OpenAI API key detected"
elif [ -n "${ANTHROPIC_API_KEY:-}" ]; then
print_success "Anthropic API key detected"
elif [ -n "${GEMINI_API_KEY:-}" ]; then
print_success "Gemini API key detected"
elif [ -n "${GROQ_API_KEY:-}" ]; then
print_success "Groq API key detected"
else
print_warning "No LLM API key detected. Set one before using Codex:"
echo -e " ${CYAN}export OPENAI_API_KEY=sk-your-key${NC}"
echo -e " ${DIM}or${NC}"
echo -e " ${CYAN}export ANTHROPIC_API_KEY=your-key${NC}"
fi
fi
# Step 6: Write hooks.json
print_step "Configuring Codex hooks"
mkdir -p "${CODEX_DIR}"
cat > "${HOOKS_FILE}" <<HOOKSEOF
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"${SCRIPTS_DIR}/session_start.py\"",
"timeout": 5
}
]
}
],
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"${SCRIPTS_DIR}/recall.py\"",
"timeout": 12
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "python3 \"${SCRIPTS_DIR}/retain.py\"",
"timeout": 30
}
]
}
]
}
}
HOOKSEOF
print_success "Hooks written to ${HOOKS_FILE}"
# Step 7: Enable codex_hooks in config.toml
if [ ! -f "${CONFIG_FILE}" ]; then
touch "${CONFIG_FILE}"
fi
if grep -q '^\[features\]' "${CONFIG_FILE}" 2>/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 ""