SHELL := /bin/bash
BINARY := rmcp-memex
INSTALL_PATH := $(HOME)/.cargo/bin/$(BINARY)
LAUNCHD_PLIST := $(HOME)/Library/LaunchAgents/ai.libraxis.rmcp-memex.plist
DB_PATH_DISK := $(HOME)/.ai-memories/lancedb
LOG_DIR := $(HOME)/.ai-memories/logs
HTTP_PORT := 8987
RAMDISK_NAME := MemexRAM
RAMDISK_SIZE_GB := 50
RAMDISK_BLOCKS := $(shell echo $$(($(RAMDISK_SIZE_GB) * 1024 * 1024 * 2)))
RAMDISK_MOUNT := /Volumes/$(RAMDISK_NAME)
DB_PATH_RAM := $(RAMDISK_MOUNT)/lancedb
DB_PATH := $(shell if [ -d "$(RAMDISK_MOUNT)" ]; then echo "$(DB_PATH_RAM)"; else echo "$(DB_PATH_DISK)"; fi)
.PHONY: help build install start stop restart status logs health dashboard clean optimize \
ramdisk-create ramdisk-mount ramdisk-up ramdisk-down snapshot ramdisk-status
help:
@echo "rmcp-memex Management"
@echo "===================="
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m %s\n", $$1, $$2}'
build:
cargo build --release
install: build
@cp ./target/release/$(BINARY) $(INSTALL_PATH)
@echo "Installed to $(INSTALL_PATH)"
start:
@if lsof -i :$(HTTP_PORT) >/dev/null 2>&1; then \
echo "Service already running on port $(HTTP_PORT)"; \
else \
launchctl bootstrap gui/$$(id -u) $(LAUNCHD_PLIST) 2>/dev/null || \
launchctl kickstart gui/$$(id -u)/ai.libraxis.rmcp-memex 2>/dev/null || \
$(INSTALL_PATH) serve --db-path $(DB_PATH) --http-port $(HTTP_PORT) --http-only & \
sleep 3; \
echo "Started memex on port $(HTTP_PORT)"; \
fi
stop:
@-launchctl bootout gui/$$(id -u)/ai.libraxis.rmcp-memex 2>/dev/null
@-pkill -f "$(BINARY) serve" 2>/dev/null
@echo "Stopped memex service"
restart: stop
@sleep 2
@$(MAKE) start
status:
@echo "=== Launchd Status ==="
@launchctl list 2>/dev/null | grep -E "rmcp|memex" || echo "No launchd service"
@echo ""
@echo "=== Port $(HTTP_PORT) ==="
@lsof -i :$(HTTP_PORT) 2>/dev/null || echo "Port $(HTTP_PORT) not in use"
@echo ""
@echo "=== Health Check ==="
@curl -s --max-time 2 http://localhost:$(HTTP_PORT)/health 2>/dev/null || echo "Server not responding"
health:
@curl -s --max-time 3 http://localhost:$(HTTP_PORT)/health | jq . 2>/dev/null || echo "Server not responding"
logs:
@tail -f $(LOG_DIR)/rmcp-memex.stderr.log
logs-error:
@grep -iE "error|panic|fail" $(LOG_DIR)/rmcp-memex.stderr.log | tail -20
dashboard:
@open http://localhost:$(HTTP_PORT)/
ramdisk-create:
@if [ -d "$(RAMDISK_MOUNT)" ]; then \
echo "RAM disk already exists at $(RAMDISK_MOUNT)"; \
else \
echo "Creating $(RAMDISK_SIZE_GB)GB RAM disk..."; \
DEVICE=$$(hdiutil attach -nomount ram://$(RAMDISK_BLOCKS)); \
diskutil erasevolume HFS+ "$(RAMDISK_NAME)" $$DEVICE; \
echo "RAM disk created at $(RAMDISK_MOUNT)"; \
fi
ramdisk-load:
@if [ ! -d "$(RAMDISK_MOUNT)" ]; then \
echo "ERROR: RAM disk not mounted. Run 'make ramdisk-create' first."; \
exit 1; \
fi
@echo "Copying LanceDB to RAM disk..."
@mkdir -p "$(DB_PATH_RAM)"
@if [ -d "$(DB_PATH_DISK)" ]; then \
rsync -av --progress "$(DB_PATH_DISK)/" "$(DB_PATH_RAM)/"; \
echo "Copied $$(du -sh $(DB_PATH_RAM) | cut -f1) to RAM disk"; \
else \
echo "No existing DB at $(DB_PATH_DISK), starting fresh"; \
fi
ramdisk-up: ramdisk-create ramdisk-load
@$(MAKE) stop 2>/dev/null || true
@sleep 1
@echo "Starting memex with RAM disk..."
@$(INSTALL_PATH) serve --db-path "$(DB_PATH_RAM)" --http-port $(HTTP_PORT) --http-only &
@sleep 3
@echo ""
@echo "=== MEMEX RAM MODE ==="
@echo "RAM disk: $(RAMDISK_MOUNT) ($(RAMDISK_SIZE_GB)GB)"
@echo "DB path: $(DB_PATH_RAM)"
@echo "Dashboard: http://localhost:$(HTTP_PORT)/"
@echo ""
@echo "IMPORTANT: Run 'make snapshot' periodically to save to disk!"
snapshot:
@if [ ! -d "$(RAMDISK_MOUNT)" ]; then \
echo "No RAM disk mounted, nothing to snapshot"; \
exit 0; \
fi
@echo "Syncing RAM disk to disk..."
@rsync -av --delete "$(DB_PATH_RAM)/" "$(DB_PATH_DISK)/"
@echo "Snapshot saved to $(DB_PATH_DISK)"
@echo "Size: $$(du -sh $(DB_PATH_DISK) | cut -f1)"
ramdisk-down: snapshot
@$(MAKE) stop 2>/dev/null || true
@if [ -d "$(RAMDISK_MOUNT)" ]; then \
echo "Unmounting RAM disk..."; \
hdiutil detach "$(RAMDISK_MOUNT)"; \
echo "RAM disk unmounted. Data saved to $(DB_PATH_DISK)"; \
else \
echo "No RAM disk to unmount"; \
fi
ramdisk-status:
@echo "=== RAM Disk Status ==="
@if [ -d "$(RAMDISK_MOUNT)" ]; then \
echo "Status: MOUNTED"; \
echo "Mount: $(RAMDISK_MOUNT)"; \
echo "Size: $$(df -h $(RAMDISK_MOUNT) | tail -1 | awk '{print $$2}')"; \
echo "Used: $$(df -h $(RAMDISK_MOUNT) | tail -1 | awk '{print $$3}')"; \
echo "Free: $$(df -h $(RAMDISK_MOUNT) | tail -1 | awk '{print $$4}')"; \
echo "DB: $$(du -sh $(DB_PATH_RAM) 2>/dev/null | cut -f1 || echo 'empty')"; \
else \
echo "Status: NOT MOUNTED"; \
echo "Run 'make ramdisk-up' to enable RAM mode"; \
fi
@echo ""
@echo "=== Disk Backup ==="
@echo "Path: $(DB_PATH_DISK)"
@echo "Size: $$(du -sh $(DB_PATH_DISK) 2>/dev/null | cut -f1 || echo 'empty')"
auto-snapshot:
@if [ ! -d "$(RAMDISK_MOUNT)" ]; then \
echo "No RAM disk mounted, auto-snapshot not needed"; \
exit 0; \
fi
@echo "Starting auto-snapshot daemon (every 15 minutes)..."
@(while true; do \
sleep 900; \
if [ -d "$(RAMDISK_MOUNT)" ]; then \
echo "$$(date): Auto-snapshot starting..." >> $(LOG_DIR)/snapshot.log; \
rsync -a --delete "$(DB_PATH_RAM)/" "$(DB_PATH_DISK)/" 2>> $(LOG_DIR)/snapshot.log; \
echo "$$(date): Auto-snapshot complete" >> $(LOG_DIR)/snapshot.log; \
fi; \
done) &
@echo "Auto-snapshot daemon started (PID: $$!)"
@echo "Logs: $(LOG_DIR)/snapshot.log"
optimize:
$(INSTALL_PATH) optimize --db-path $(DB_PATH)
stats:
$(INSTALL_PATH) stats --db-path $(DB_PATH)
namespaces:
$(INSTALL_PATH) namespaces --stats --db-path $(DB_PATH)
dev:
RUST_LOG=debug cargo run -- serve --db-path $(DB_PATH) --http-port $(HTTP_PORT) --http-only
test:
cargo test
check:
cargo check
clean:
cargo clean
up: install restart
@echo "Service updated and restarted"
down: stop
ps: status
ram: ramdisk-up auto-snapshot
@echo ""
@echo "=== MEMEX FULL RAM MODE ACTIVE ==="
@echo "All 25GB+ in RAM. Auto-snapshot every 15 min."
@echo "Run 'make ramdisk-down' before shutdown!"