Files
claude-mnemonic/Makefile
T
lukaszraczylo f07875ee82 fix: plugin no longer vanishes after Claude Code updates
Root cause: plugin registered as directory source in known_marketplaces.json,
which gets wiped on CLI updates. Now registers in extraKnownMarketplaces
(settings.json) as a GitHub source — same mechanism caveman/context-mode use.

Binaries install to ~/.claude-mnemonic/bin/ instead of the Claude-managed
plugins directory. Thin wrapper scripts in the repo let the marketplace
clone find them. Nothing gets cleaned up when Claude refreshes its cache.

Also fixed along the way:
- ONNX Runtime 1.24.3 → 1.26.0 (API v25 mismatch broke all embedding tests)
- Vector client leaked on DB reinit, processQueue had a race on sessionManager
- reloadConfig called os.Exit(0) bypassing graceful shutdown
- Removed dead QueryRowWithTimeout that leaked contexts
- Added tests for graph/watcher/maintenance/update (all were at 0%)
2026-05-24 01:56:54 +01:00

261 lines
12 KiB
Makefile

# Claude Mnemonic Makefile
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
# Pass version to both main package and hooks package
LDFLAGS := -ldflags "-X main.Version=$(VERSION) -X github.com/lukaszraczylo/claude-mnemonic/pkg/hooks.Version=$(VERSION) -s -w" -buildvcs=false
BUILD_DIR := bin
PLUGIN_DIR := plugin
STABLE_BIN := $(HOME)/.claude-mnemonic/bin
# Go settings
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)
# CGO settings for SQLite FTS5 support
export CGO_ENABLED=1
BUILD_TAGS := -tags "fts5"
.PHONY: all build clean test install lint hooks worker mcp stop-worker start-worker restart-worker dashboard website dev-website setup-libs update-version
all: build
# Download ONNX runtime libraries (all platforms for local dev, skips if present)
setup-libs:
@./scripts/download-onnx-libs.sh all
# Update version in committed plugin metadata
update-version:
@if [ -f .claude-plugin/plugin.json ]; then \
sed 's/"version": "[^"]*"/"version": "$(VERSION)"/' .claude-plugin/plugin.json > .claude-plugin/plugin.json.tmp && mv .claude-plugin/plugin.json.tmp .claude-plugin/plugin.json; \
echo "Updated .claude-plugin/plugin.json to version $(VERSION)"; \
fi
@if [ -f marketplace.json ]; then \
sed 's/"version": "[^"]*"/"version": "$(VERSION)"/' marketplace.json > marketplace.json.tmp && mv marketplace.json.tmp marketplace.json; \
echo "Updated marketplace.json version fields to $(VERSION)"; \
fi
# Build all binaries
build: setup-libs update-version dashboard worker hooks mcp
# Build Vue dashboard
dashboard:
@echo "Building Vue dashboard..."
@sed 's/{{ .Version }}/$(VERSION)/g' ui/package.json.tpl > ui/package.json
@cd ui && npm install --silent && npm run build
@rm -rf internal/worker/static
@mkdir -p internal/worker/static
@touch internal/worker/static/placeholder.html
@cp -r ui/dist/* internal/worker/static/
# Build worker service
worker:
@echo "Building worker..."
@mkdir -p $(BUILD_DIR)
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/worker ./cmd/worker
# Build all hooks
hooks:
@echo "Building hooks..."
@mkdir -p $(BUILD_DIR)/hooks
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/hooks/session-start ./cmd/hooks/session-start
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/hooks/user-prompt ./cmd/hooks/user-prompt
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/hooks/post-tool-use ./cmd/hooks/post-tool-use
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/hooks/subagent-stop ./cmd/hooks/subagent-stop
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/hooks/stop ./cmd/hooks/stop
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/hooks/statusline ./cmd/hooks/statusline
# Build MCP server
mcp:
@echo "Building MCP server..."
@mkdir -p $(BUILD_DIR)
go build $(BUILD_TAGS) $(LDFLAGS) -o $(BUILD_DIR)/mcp-server ./cmd/mcp
# Build for all platforms
build-all: build-linux build-darwin build-windows
build-linux:
@echo "Building for Linux..."
@mkdir -p $(BUILD_DIR)/linux-amd64/hooks
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/worker ./cmd/worker
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/mcp-server ./cmd/mcp
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/hooks/session-start ./cmd/hooks/session-start
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/hooks/user-prompt ./cmd/hooks/user-prompt
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/hooks/post-tool-use ./cmd/hooks/post-tool-use
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/hooks/subagent-stop ./cmd/hooks/subagent-stop
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/hooks/stop ./cmd/hooks/stop
GOOS=linux GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/linux-amd64/hooks/statusline ./cmd/hooks/statusline
build-darwin:
@echo "Building for macOS..."
@mkdir -p $(BUILD_DIR)/darwin-amd64/hooks $(BUILD_DIR)/darwin-arm64/hooks
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/worker ./cmd/worker
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/worker ./cmd/worker
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/mcp-server ./cmd/mcp
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/mcp-server ./cmd/mcp
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/hooks/session-start ./cmd/hooks/session-start
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/hooks/session-start ./cmd/hooks/session-start
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/hooks/user-prompt ./cmd/hooks/user-prompt
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/hooks/user-prompt ./cmd/hooks/user-prompt
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/hooks/post-tool-use ./cmd/hooks/post-tool-use
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/hooks/post-tool-use ./cmd/hooks/post-tool-use
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/hooks/subagent-stop ./cmd/hooks/subagent-stop
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/hooks/subagent-stop ./cmd/hooks/subagent-stop
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/hooks/stop ./cmd/hooks/stop
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/hooks/stop ./cmd/hooks/stop
GOOS=darwin GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-amd64/hooks/statusline ./cmd/hooks/statusline
GOOS=darwin GOARCH=arm64 go build $(LDFLAGS) -o $(BUILD_DIR)/darwin-arm64/hooks/statusline ./cmd/hooks/statusline
build-windows:
@echo "Building for Windows..."
@mkdir -p $(BUILD_DIR)/windows-amd64/hooks
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/worker.exe ./cmd/worker
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/mcp-server.exe ./cmd/mcp
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/hooks/session-start.exe ./cmd/hooks/session-start
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/hooks/user-prompt.exe ./cmd/hooks/user-prompt
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/hooks/post-tool-use.exe ./cmd/hooks/post-tool-use
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/hooks/subagent-stop.exe ./cmd/hooks/subagent-stop
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/hooks/stop.exe ./cmd/hooks/stop
GOOS=windows GOARCH=amd64 go build $(LDFLAGS) -o $(BUILD_DIR)/windows-amd64/hooks/statusline.exe ./cmd/hooks/statusline
# Stop any running worker
stop-worker:
@echo "Stopping worker..."
@-pkill -TERM -f 'claude-mnemonic.*worker' 2>/dev/null || true
@-pkill -TERM -f '\.claude-mnemonic/bin/worker' 2>/dev/null || true
@-pkill -TERM -f '\.claude/plugins/.*/worker' 2>/dev/null || true
@sleep 1
@-pkill -9 -f 'claude-mnemonic.*worker' 2>/dev/null || true
@-pkill -9 -f '\.claude-mnemonic/bin/worker' 2>/dev/null || true
@-pkill -9 -f '\.claude/plugins/.*/worker' 2>/dev/null || true
@-lsof -ti :37777 | xargs kill -9 2>/dev/null || true
@sleep 1
# Start worker in background
start-worker:
@echo "Starting worker..."
@nohup $(STABLE_BIN)/worker > /tmp/claude-mnemonic-worker.log 2>&1 &
@sleep 1
@if curl -s http://localhost:37777/health > /dev/null 2>&1; then \
echo "Worker started successfully (http://localhost:37777)"; \
else \
echo "Warning: Worker may not have started. Check /tmp/claude-mnemonic-worker.log"; \
fi
# Restart worker
restart-worker: stop-worker start-worker
# Install to stable binary location and register with Claude Code
install: build stop-worker
@echo "Installing claude-mnemonic..."
@# Verify build output binaries exist
@test -f $(BUILD_DIR)/worker || { echo "ERROR: $(BUILD_DIR)/worker not found. Build may have failed."; exit 1; }
@test -f $(BUILD_DIR)/mcp-server || { echo "ERROR: $(BUILD_DIR)/mcp-server not found. Build may have failed."; exit 1; }
@test -d $(BUILD_DIR)/hooks || { echo "ERROR: $(BUILD_DIR)/hooks not found. Build may have failed."; exit 1; }
@# Install binaries to stable location (survives Claude Code updates)
@mkdir -p $(STABLE_BIN)/hooks
cp $(BUILD_DIR)/worker $(STABLE_BIN)/
cp $(BUILD_DIR)/mcp-server $(STABLE_BIN)/
cp $(BUILD_DIR)/hooks/* $(STABLE_BIN)/hooks/
@echo "Binaries installed to $(STABLE_BIN)"
@# Set up marketplace directory with wrapper scripts and metadata
@mkdir -p $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/.claude-plugin
@mkdir -p $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/hooks
@mkdir -p $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/commands
@cp .claude-plugin/plugin.json $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/.claude-plugin/
@cp marketplace.json $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/.claude-plugin/marketplace.json 2>/dev/null || true
@cp hooks/hooks.json $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/hooks/
@cp hooks/session-start hooks/user-prompt hooks/post-tool-use hooks/stop hooks/subagent-stop hooks/statusline $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/hooks/
@chmod +x $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/hooks/*
@cp mcp-server $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/
@chmod +x $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/mcp-server
@cp commands/restart.md $(HOME)/.claude/plugins/marketplaces/claude-mnemonic/commands/
@echo "Registering plugin with Claude Code..."
@./scripts/register-plugin.sh "$(VERSION)"
@$(MAKE) start-worker
@echo "Installation complete!"
# Uninstall
uninstall: stop-worker
@echo "Uninstalling..."
@./scripts/unregister-plugin.sh
rm -rf $(HOME)/.claude/plugins/marketplaces/claude-mnemonic
@echo "Uninstallation complete!"
# Run tests (with FTS5 support)
test: setup-libs
go test $(BUILD_TAGS) -v -race ./...
# Run tests with coverage (with FTS5 support)
test-coverage: setup-libs
go test $(BUILD_TAGS) -v -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
@go tool cover -func=coverage.out | tail -1
# Run benchmarks
bench:
go test -bench=. -benchmem ./...
# Run linter
lint:
golangci-lint run ./...
# Format code
fmt:
go fmt ./...
# Clean build artifacts
clean:
rm -rf $(BUILD_DIR)
rm -f coverage.out coverage.html
# Run worker in development mode
dev: worker
./$(BUILD_DIR)/worker
# Download dependencies
deps:
go mod download
go mod tidy
# Build website for production
website:
@echo "Building website..."
@cd docs && npm install --silent && npm run build
@echo "Website built to docs/dist/"
# Run website in development mode
dev-website:
@echo "Starting website dev server..."
@cd docs && npm install --silent && npm run dev
# Show help
help:
@echo "Claude Mnemonic Build System"
@echo ""
@echo "Usage:"
@echo " make build - Build all binaries"
@echo " make worker - Build worker service only"
@echo " make mcp - Build MCP server only"
@echo " make hooks - Build hooks only"
@echo " make build-all - Build for all platforms"
@echo " make install - Install to Claude plugins directory (restarts worker)"
@echo " make uninstall - Remove from Claude plugins directory"
@echo " make stop-worker - Stop the running worker"
@echo " make start-worker - Start the worker in background"
@echo " make restart-worker - Restart the worker"
@echo " make test - Run tests"
@echo " make bench - Run benchmarks"
@echo " make lint - Run linter"
@echo " make fmt - Format code"
@echo " make clean - Clean build artifacts"
@echo " make dev - Run worker in development mode"
@echo " make update-version - Update version in plugin metadata files"
@echo " make deps - Download dependencies"
@echo " make website - Build website for production"
@echo " make dev-website - Run website dev server"
@echo ""
@echo "Variables:"
@echo " VERSION=$(VERSION)"
@echo " GOOS=$(GOOS)"
@echo " GOARCH=$(GOARCH)"