11#! /usr/bin/env bash
2- # mem install script — installs the binary and wires Claude Code hooks .
2+ # mem install script — one command, fully wired .
33# Usage: curl -fsSL https://raw.githubusercontent.com/HugoLopes45/mem/main/install.sh | bash
44set -euo pipefail
55
66REPO=" HugoLopes45/mem"
77BIN_NAME=" mem"
8- INSTALL_DIR=" ${MEM_INSTALL_DIR:- $HOME / .local/ bin} "
9- HOOKS_DIR=" ${MEM_HOOKS_DIR:- $HOME / .claude/ hooks} "
8+ INSTALL_DIR=" ${MEM_INSTALL_DIR:- $HOME / .cargo/ bin} "
109
11- # ── Colors ────────────────────────────────────────────────────────────────────
1210RED=' \033[0;31m' ; GREEN=' \033[0;32m' ; YELLOW=' \033[1;33m' ; BOLD=' \033[1m' ; RESET=' \033[0m'
1311info () { echo -e " ${BOLD} [mem]${RESET} $* " ; }
1412success () { echo -e " ${GREEN} [mem]${RESET} $* " ; }
@@ -21,16 +19,16 @@ ARCH=$(uname -m)
2119case " $ARCH " in
2220 x86_64) ARCH=" x86_64" ;;
2321 aarch64|arm64) ARCH=" aarch64" ;;
24- * ) error " Unsupported architecture: $ARCH . Build from source with : cargo install --git https://github.com/$REPO " ;;
22+ * ) error " Unsupported architecture: $ARCH . Build from source: cargo install --git https://github.com/$REPO " ;;
2523esac
2624
2725case " $OS " in
2826 linux) TARGET=" ${ARCH} -unknown-linux-musl" ;;
2927 darwin) TARGET=" ${ARCH} -apple-darwin" ;;
30- * ) error " Unsupported OS: $OS . Build from source with : cargo install --git https://github.com/$REPO " ;;
28+ * ) error " Unsupported OS: $OS . Build from source: cargo install --git https://github.com/$REPO " ;;
3129esac
3230
33- # ── Find latest release ───────────────────────────────────────────────────────
31+ # ── Fetch latest release ───────────────────────────────────────────────────────
3432info " Fetching latest release..."
3533if command -v curl > /dev/null 2>&1 ; then
3634 FETCH=" curl -fsSL"
4341LATEST=$( $FETCH " https://api.github.com/repos/$REPO /releases/latest" \
4442 | grep ' "tag_name"' | sed ' s/.*"tag_name": *"\(.*\)".*/\1/' )
4543
46- if [ -z " $LATEST " ]; then
47- # No release yet — fall back to cargo install from source
48- warn " No release found. Installing from source via cargo..."
44+ INSTALLED_VIA=" "
45+
46+ install_from_source () {
47+ warn " ${1:- Falling back to cargo install from source...} "
4948 if ! command -v cargo > /dev/null 2>&1 ; then
5049 error " cargo not found. Install Rust: https://rustup.rs"
5150 fi
5251 cargo install --git " https://github.com/$REPO " --locked
5352 INSTALLED_VIA=" cargo"
53+ }
54+
55+ if [ -z " $LATEST " ]; then
56+ install_from_source " No release found."
5457else
5558 ARCHIVE=" ${BIN_NAME} -${LATEST} -${TARGET} .tar.gz"
5659 URL=" https://github.com/$REPO /releases/download/${LATEST} /${ARCHIVE} "
5962 TMP=$( mktemp -d)
6063 trap ' rm -rf "$TMP"' EXIT
6164
62- install_from_source () {
63- warn " Pre-built binary not found for $TARGET . Falling back to cargo install..."
64- if ! command -v cargo > /dev/null 2>&1 ; then
65- error " cargo not found. Install Rust: https://rustup.rs"
66- fi
67- cargo install --git " https://github.com/$REPO " --locked
68- INSTALLED_VIA=" cargo"
69- }
70-
65+ downloaded=0
7166 if command -v curl > /dev/null 2>&1 ; then
72- if ! curl -fsSL -o " $TMP /$ARCHIVE " " $URL " 2> /dev/null; then
73- install_from_source
74- fi
67+ curl -fsSL -o " $TMP /$ARCHIVE " " $URL " 2> /dev/null && downloaded=1
7568 else
76- if ! wget -q -O " $TMP /$ARCHIVE " " $URL " 2> /dev/null; then
77- install_from_source
78- fi
69+ wget -q -O " $TMP /$ARCHIVE " " $URL " 2> /dev/null && downloaded=1
7970 fi
8071
81- if [ -z " ${INSTALLED_VIA:- } " ]; then
82- if ! tar -xzf " $TMP /$ARCHIVE " -C " $TMP " 2> /dev/null; then
83- error " Failed to extract archive. Download may be corrupted. Try: cargo install --git https://github.com/$REPO "
84- fi
72+ if [ " $downloaded " = " 1" ] && tar -xzf " $TMP /$ARCHIVE " -C " $TMP " 2> /dev/null; then
8573 mkdir -p " $INSTALL_DIR "
8674 mv " $TMP /$BIN_NAME " " $INSTALL_DIR /$BIN_NAME "
8775 chmod +x " $INSTALL_DIR /$BIN_NAME "
8876 INSTALLED_VIA=" binary"
77+ else
78+ install_from_source " Pre-built binary unavailable for $TARGET ."
8979 fi
9080fi
9181
92- # ── Verify ──── ────────────────────────────────────────────────────────────────
93- if [ " $INSTALLED_VIA " = " binary " ] && ! command -v " $BIN_NAME " > /dev/null 2>&1 ; then
82+ # ── PATH check ────────────────────────────────────────────────────────────────
83+ if ! command -v " $BIN_NAME " > /dev/null 2>&1 ; then
9484 warn " $INSTALL_DIR is not in your PATH."
9585 warn " Add to your shell profile: export PATH=\"\$ PATH:$INSTALL_DIR \" "
86+ warn " Then re-run: mem init"
87+ success " Installed $BIN_NAME ($INSTALLED_VIA ) — add to PATH then run: mem init"
88+ exit 0
9689fi
9790
9891success " Installed $BIN_NAME ($INSTALLED_VIA )"
9992
100- # ── Install hook scripts ──────────────────────────────────────────────────────
101- info " Installing hook scripts to $HOOKS_DIR ..."
102- mkdir -p " $HOOKS_DIR "
103-
104- HOOKS_SRC=" $( dirname " ${BASH_SOURCE[0]} " ) /hooks"
105- if [ ! -d " $HOOKS_SRC " ]; then
106- # Downloaded via curl — fetch hooks from GitHub
107- for HOOK in mem-stop.sh mem-precompact.sh mem-session-start.sh; do
108- HOOK_URL=" https://raw.githubusercontent.com/$REPO /main/hooks/$HOOK "
109- if command -v curl > /dev/null 2>&1 ; then
110- curl -fsSL -o " $HOOKS_DIR /$HOOK " " $HOOK_URL " 2> /dev/null || \
111- error " Failed to download hook $HOOK "
112- else
113- wget -q -O " $HOOKS_DIR /$HOOK " " $HOOK_URL " 2> /dev/null || \
114- error " Failed to download hook $HOOK "
115- fi
116- chmod +x " $HOOKS_DIR /$HOOK "
117- done
118- else
119- cp " $HOOKS_SRC " /mem-* .sh " $HOOKS_DIR /"
120- chmod +x " $HOOKS_DIR " /mem-* .sh
121- fi
122-
123- success " Hook scripts installed to $HOOKS_DIR "
93+ # ── Wire hooks — the whole point ──────────────────────────────────────────────
94+ info " Wiring Claude Code hooks..."
95+ " $BIN_NAME " init
12496
125- # ── Done ──────────────────────────────────────────────────────────────────────
126- echo " "
127- echo -e " ${BOLD} Next step:${RESET} Add hooks to ~/.claude/settings.json:"
128- echo " "
129- cat << 'HOOKS '
130- {
131- "hooks": {
132- "Stop": [{"hooks": [{"type": "command", "command": "~/.claude/hooks/mem-stop.sh"}]}],
133- "PreCompact": [{"matcher": "auto", "hooks": [{"type": "command", "command": "~/.claude/hooks/mem-precompact.sh"}]}],
134- "SessionStart": [{"hooks": [{"type": "command", "command": "~/.claude/hooks/mem-session-start.sh"}]}]
135- }
136- }
137- HOOKS
97+ success " Done. mem is fully wired."
13898echo " "
139- echo -e " Run ${BOLD} mem stats${RESET} to verify the installation."
99+ echo -e " ${BOLD} mem status${RESET} — verify installation"
100+ echo -e " ${BOLD} mem search${RESET} — search your session memories"
101+ echo -e " ${BOLD} mem gain${RESET} — token analytics"
0 commit comments