Initial commit

This commit is contained in:
2025-12-14 21:59:59 +00:00
commit 9c2a1a795a
126 changed files with 21728 additions and 0 deletions
+256
View File
@@ -0,0 +1,256 @@
# Claude Mnemonic - Windows Installation Script
# Usage: irm https://raw.githubusercontent.com/lukaszraczylo/claude-mnemonic/main/scripts/install.ps1 | iex
#
# Or with a specific version:
# $env:MNEMONIC_VERSION = "v1.0.0"; irm https://raw.githubusercontent.com/lukaszraczylo/claude-mnemonic/main/scripts/install.ps1 | iex
param(
[string]$Version = $env:MNEMONIC_VERSION,
[switch]$Uninstall
)
$ErrorActionPreference = "Stop"
# Configuration
$GitHubRepo = "lukaszraczylo/claude-mnemonic"
$InstallDir = "$env:USERPROFILE\.claude\plugins\marketplaces\claude-mnemonic"
$CacheDir = "$env:USERPROFILE\.claude\plugins\cache\claude-mnemonic\claude-mnemonic"
$PluginsFile = "$env:USERPROFILE\.claude\plugins\installed_plugins.json"
$SettingsFile = "$env:USERPROFILE\.claude\settings.json"
$MarketplacesFile = "$env:USERPROFILE\.claude\plugins\known_marketplaces.json"
$PluginKey = "claude-mnemonic@claude-mnemonic"
function Write-Info { param($Message) Write-Host "[INFO] $Message" -ForegroundColor Blue }
function Write-Success { param($Message) Write-Host "[OK] $Message" -ForegroundColor Green }
function Write-Warn { param($Message) Write-Host "[WARN] $Message" -ForegroundColor Yellow }
function Write-Error { param($Message) Write-Host "[ERROR] $Message" -ForegroundColor Red; exit 1 }
function Get-LatestVersion {
try {
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$GitHubRepo/releases/latest"
return $release.tag_name
} catch {
Write-Error "Failed to fetch latest version from GitHub: $_"
}
}
function Stop-ExistingWorker {
Write-Info "Stopping existing worker (if running)..."
Get-Process | Where-Object { $_.ProcessName -like "*worker*" -and $_.Path -like "*claude-mnemonic*" } | Stop-Process -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
}
function Install-Release {
param([string]$Version)
$TempDir = New-Item -ItemType Directory -Path "$env:TEMP\claude-mnemonic-$(Get-Random)" -Force
try {
# Construct download URL
$VersionClean = $Version -replace "^v", ""
$ArchiveName = "claude-mnemonic_${VersionClean}_windows_amd64.zip"
$DownloadUrl = "https://github.com/$GitHubRepo/releases/download/$Version/$ArchiveName"
Write-Info "Downloading $ArchiveName..."
$ZipPath = Join-Path $TempDir "release.zip"
Invoke-WebRequest -Uri $DownloadUrl -OutFile $ZipPath -UseBasicParsing
Write-Info "Extracting archive..."
Expand-Archive -Path $ZipPath -DestinationPath $TempDir -Force
Stop-ExistingWorker
# Create installation directories
Write-Info "Installing to $InstallDir..."
New-Item -ItemType Directory -Path "$InstallDir\hooks" -Force | Out-Null
New-Item -ItemType Directory -Path "$InstallDir\.claude-plugin" -Force | Out-Null
# Copy binaries
Copy-Item "$TempDir\worker.exe" "$InstallDir\" -Force
Copy-Item "$TempDir\mcp-server.exe" "$InstallDir\" -Force
Copy-Item "$TempDir\hooks\*" "$InstallDir\hooks\" -Force
# Copy plugin configuration
Copy-Item "$TempDir\.claude-plugin\*" "$InstallDir\.claude-plugin\" -Force
Write-Success "Binaries installed to $InstallDir"
} finally {
Remove-Item -Recurse -Force $TempDir -ErrorAction SilentlyContinue
}
}
function Register-Plugin {
param([string]$Version)
$Timestamp = (Get-Date).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.000Z")
$VersionClean = $Version -replace "^v", ""
$CachePath = "$CacheDir\$VersionClean"
# Ensure directories exist
New-Item -ItemType Directory -Path "$env:USERPROFILE\.claude\plugins" -Force | Out-Null
New-Item -ItemType Directory -Path $CachePath -Force | Out-Null
# Create JSON files if they don't exist
if (-not (Test-Path $PluginsFile)) {
'{"version": 2, "plugins": {}}' | Out-File -Encoding UTF8 $PluginsFile
}
if (-not (Test-Path $SettingsFile)) {
'{}' | Out-File -Encoding UTF8 $SettingsFile
}
if (-not (Test-Path $MarketplacesFile)) {
'{}' | Out-File -Encoding UTF8 $MarketplacesFile
}
# Copy files to cache directory
New-Item -ItemType Directory -Path "$CachePath\.claude-plugin" -Force | Out-Null
New-Item -ItemType Directory -Path "$CachePath\hooks" -Force | Out-Null
Copy-Item "$InstallDir\*" $CachePath -Recurse -Force -ErrorAction SilentlyContinue
try {
# Update installed_plugins.json
$Plugins = Get-Content $PluginsFile -Raw | ConvertFrom-Json
$PluginEntry = @(
@{
scope = "user"
installPath = $CachePath
version = $VersionClean
installedAt = $Timestamp
lastUpdated = $Timestamp
isLocal = $true
}
)
if (-not $Plugins.plugins) {
$Plugins | Add-Member -NotePropertyName "plugins" -NotePropertyValue @{} -Force
}
$Plugins.plugins | Add-Member -NotePropertyName $PluginKey -NotePropertyValue $PluginEntry -Force
$Plugins | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $PluginsFile
Write-Success "Plugin registered in installed_plugins.json"
# Update settings.json
$Settings = Get-Content $SettingsFile -Raw | ConvertFrom-Json
if (-not $Settings.enabledPlugins) {
$Settings | Add-Member -NotePropertyName "enabledPlugins" -NotePropertyValue @{} -Force
}
$Settings.enabledPlugins | Add-Member -NotePropertyName $PluginKey -NotePropertyValue $true -Force
$Settings | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $SettingsFile
Write-Success "Plugin enabled in settings.json"
# Update known_marketplaces.json
$Marketplaces = Get-Content $MarketplacesFile -Raw | ConvertFrom-Json
$MarketplaceEntry = @{
source = @{
source = "directory"
path = $InstallDir
}
installLocation = $InstallDir
lastUpdated = $Timestamp
}
$Marketplaces | Add-Member -NotePropertyName "claude-mnemonic" -NotePropertyValue $MarketplaceEntry -Force
$Marketplaces | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $MarketplacesFile
Write-Success "Marketplace registered in known_marketplaces.json"
} catch {
Write-Warn "Plugin registration encountered an error: $_"
}
}
function Start-Worker {
$WorkerPath = Join-Path $InstallDir "worker.exe"
if (-not (Test-Path $WorkerPath)) {
Write-Error "Worker binary not found at $WorkerPath"
}
Write-Info "Starting worker service..."
Start-Process -FilePath $WorkerPath -WindowStyle Hidden
Start-Sleep -Seconds 2
try {
$response = Invoke-WebRequest -Uri "http://localhost:37777/health" -UseBasicParsing -TimeoutSec 5
Write-Success "Worker started successfully at http://localhost:37777"
} catch {
Write-Warn "Worker may not have started properly. Check the process manually."
}
}
function Uninstall-ClaudeMnemonic {
param([switch]$KeepData)
Write-Info "Uninstalling Claude Mnemonic..."
Stop-ExistingWorker
# Remove directories
Remove-Item -Recurse -Force $InstallDir -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force $CacheDir -ErrorAction SilentlyContinue
# Remove from JSON files
try {
if (Test-Path $PluginsFile) {
$Plugins = Get-Content $PluginsFile -Raw | ConvertFrom-Json
$Plugins.plugins.PSObject.Properties.Remove($PluginKey)
$Plugins | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $PluginsFile
}
if (Test-Path $SettingsFile) {
$Settings = Get-Content $SettingsFile -Raw | ConvertFrom-Json
if ($Settings.enabledPlugins) {
$Settings.enabledPlugins.PSObject.Properties.Remove($PluginKey)
$Settings | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $SettingsFile
}
}
if (Test-Path $MarketplacesFile) {
$Marketplaces = Get-Content $MarketplacesFile -Raw | ConvertFrom-Json
$Marketplaces.PSObject.Properties.Remove("claude-mnemonic")
$Marketplaces | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $MarketplacesFile
}
} catch {
Write-Warn "Error cleaning up JSON files: $_"
}
# Handle data directory
$DataDir = "$env:USERPROFILE\.claude-mnemonic"
if (Test-Path $DataDir) {
if ($KeepData) {
Write-Warn "Keeping data directory: $DataDir"
} else {
Remove-Item -Recurse -Force $DataDir -ErrorAction SilentlyContinue
Write-Success "Data directory removed"
}
}
Write-Success "Claude Mnemonic uninstalled successfully"
}
# Main
Write-Host ""
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Claude Mnemonic - Windows Installation Script " -ForegroundColor Cyan
Write-Host " Persistent Memory System for Claude Code " -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
if ($Uninstall) {
Uninstall-ClaudeMnemonic
exit 0
}
# Get version
if (-not $Version) {
Write-Info "Fetching latest release..."
$Version = Get-LatestVersion
}
Write-Info "Installing version: $Version"
# Install
Install-Release -Version $Version
Register-Plugin -Version $Version
Start-Worker
Write-Host ""
Write-Host "================================================================" -ForegroundColor Green
Write-Host " Installation Complete! " -ForegroundColor Green
Write-Host "================================================================" -ForegroundColor Green
Write-Host " Dashboard: http://localhost:37777" -ForegroundColor White
Write-Host ""
Write-Host " Start a new Claude Code session to activate memory." -ForegroundColor White
Write-Host "================================================================" -ForegroundColor Green
Write-Host ""
+424
View File
@@ -0,0 +1,424 @@
#!/bin/bash
# Claude Mnemonic - Remote Installation Script
# Usage: curl -sSL https://raw.githubusercontent.com/lukaszraczylo/claude-mnemonic/main/scripts/install.sh | bash
#
# Or with a specific version:
# curl -sSL https://raw.githubusercontent.com/lukaszraczylo/claude-mnemonic/main/scripts/install.sh | bash -s -- v1.0.0
set -e
# Configuration
GITHUB_REPO="lukaszraczylo/claude-mnemonic"
INSTALL_DIR="$HOME/.claude/plugins/marketplaces/claude-mnemonic"
CACHE_DIR="$HOME/.claude/plugins/cache/claude-mnemonic/claude-mnemonic"
PLUGINS_FILE="$HOME/.claude/plugins/installed_plugins.json"
SETTINGS_FILE="$HOME/.claude/settings.json"
MARKETPLACES_FILE="$HOME/.claude/plugins/known_marketplaces.json"
PLUGIN_KEY="claude-mnemonic@claude-mnemonic"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
success() {
echo -e "${GREEN}[OK]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
# Detect OS and architecture
detect_platform() {
local os arch
case "$(uname -s)" in
Darwin)
os="darwin"
;;
Linux)
os="linux"
;;
MINGW*|MSYS*|CYGWIN*)
os="windows"
;;
*)
error "Unsupported operating system: $(uname -s)"
;;
esac
case "$(uname -m)" in
x86_64|amd64)
arch="amd64"
;;
arm64|aarch64)
arch="arm64"
;;
*)
error "Unsupported architecture: $(uname -m)"
;;
esac
# Check for unsupported combinations
if [[ "$os" == "linux" && "$arch" == "arm64" ]]; then
error "Linux ARM64 is not currently supported due to CGO cross-compilation limitations"
fi
echo "${os}_${arch}"
}
# Get the latest release version from GitHub
get_latest_version() {
local version
version=$(curl -sS "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
if [[ -z "$version" ]]; then
error "Failed to fetch latest version from GitHub"
fi
echo "$version"
}
# Download and extract the release
download_release() {
local version="$1"
local platform="$2"
local tmp_dir
tmp_dir=$(mktemp -d)
trap "rm -rf $tmp_dir" EXIT
# Construct download URL
local archive_name="claude-mnemonic_${version#v}_${platform}.tar.gz"
local download_url="https://github.com/${GITHUB_REPO}/releases/download/${version}/${archive_name}"
info "Downloading ${archive_name}..."
if ! curl -sSL -o "$tmp_dir/release.tar.gz" "$download_url"; then
error "Failed to download release from: $download_url"
fi
info "Extracting archive..."
if ! tar -xzf "$tmp_dir/release.tar.gz" -C "$tmp_dir"; then
error "Failed to extract archive"
fi
# Stop existing worker if running
info "Stopping existing worker (if running)..."
pkill -9 -f 'claude-mnemonic.*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
# Create installation directories
info "Installing to ${INSTALL_DIR}..."
mkdir -p "$INSTALL_DIR/hooks"
mkdir -p "$INSTALL_DIR/.claude-plugin"
# Copy binaries
cp "$tmp_dir/worker" "$INSTALL_DIR/"
cp "$tmp_dir/mcp-server" "$INSTALL_DIR/"
cp "$tmp_dir/hooks/"* "$INSTALL_DIR/hooks/"
# Copy plugin configuration
cp "$tmp_dir/.claude-plugin/"* "$INSTALL_DIR/.claude-plugin/"
# Make binaries executable
chmod +x "$INSTALL_DIR/worker"
chmod +x "$INSTALL_DIR/mcp-server"
chmod +x "$INSTALL_DIR/hooks/"*
success "Binaries installed to ${INSTALL_DIR}"
}
# Register the plugin with Claude Code
register_plugin() {
local version="$1"
local timestamp
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
# Ensure directories exist
mkdir -p "$HOME/.claude/plugins"
mkdir -p "${CACHE_DIR}/${version}"
# Create JSON files if they don't exist
[[ ! -f "$PLUGINS_FILE" ]] && echo '{"version": 2, "plugins": {}}' > "$PLUGINS_FILE"
[[ ! -f "$SETTINGS_FILE" ]] && echo '{}' > "$SETTINGS_FILE"
[[ ! -f "$MARKETPLACES_FILE" ]] && echo '{}' > "$MARKETPLACES_FILE"
# Check for jq
if ! command -v jq &> /dev/null; then
warn "jq is not installed. Plugin registration requires jq."
warn "Please install jq: brew install jq (macOS) or apt-get install jq (Linux)"
warn "Then run: $0 --register-only"
return 1
fi
local cache_path="${CACHE_DIR}/${version}"
# Copy files to cache directory
mkdir -p "$cache_path/.claude-plugin"
mkdir -p "$cache_path/hooks"
cp -r "$INSTALL_DIR/"* "$cache_path/" 2>/dev/null || true
# Register in installed_plugins.json
local plugin_entry
plugin_entry=$(cat <<EOF
[{
"scope": "user",
"installPath": "$cache_path",
"version": "${version#v}",
"installedAt": "$timestamp",
"lastUpdated": "$timestamp",
"isLocal": true
}]
EOF
)
jq --arg key "$PLUGIN_KEY" --argjson entry "$plugin_entry" \
'.plugins[$key] = $entry' "$PLUGINS_FILE" > "${PLUGINS_FILE}.tmp" \
&& mv "${PLUGINS_FILE}.tmp" "$PLUGINS_FILE"
success "Plugin registered in installed_plugins.json"
# Enable in settings.json
jq --arg key "$PLUGIN_KEY" \
'.enabledPlugins //= {} | .enabledPlugins[$key] = true' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" \
&& mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
success "Plugin enabled in settings.json"
# Register marketplace
local marketplace_entry
marketplace_entry=$(cat <<EOF
{
"source": {
"source": "directory",
"path": "$INSTALL_DIR"
},
"installLocation": "$INSTALL_DIR",
"lastUpdated": "$timestamp"
}
EOF
)
jq --arg key "claude-mnemonic" --argjson entry "$marketplace_entry" \
'.[$key] = $entry' "$MARKETPLACES_FILE" > "${MARKETPLACES_FILE}.tmp" \
&& mv "${MARKETPLACES_FILE}.tmp" "$MARKETPLACES_FILE"
success "Marketplace registered in known_marketplaces.json"
}
# Start the worker service
start_worker() {
local worker_path="$INSTALL_DIR/worker"
if [[ ! -x "$worker_path" ]]; then
error "Worker binary not found at $worker_path"
fi
info "Starting worker service..."
nohup "$worker_path" > /tmp/claude-mnemonic-worker.log 2>&1 &
sleep 2
if curl -sS http://localhost:37777/health > /dev/null 2>&1; then
success "Worker started successfully at http://localhost:37777"
else
warn "Worker may not have started properly. Check /tmp/claude-mnemonic-worker.log"
fi
}
# Check optional dependencies for semantic search
check_optional_deps() {
local missing_deps=()
local install_hints=""
# Check for Python 3.13+
if command -v python3 &> /dev/null; then
local py_version=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")' 2>/dev/null)
if [[ "$py_version" < "3.13" ]]; then
missing_deps+=("Python 3.13+ (found $py_version)")
fi
else
missing_deps+=("Python 3.13+")
fi
# Check for uvx
if ! command -v uvx &> /dev/null; then
missing_deps+=("uvx")
fi
if [[ ${#missing_deps[@]} -gt 0 ]]; then
echo ""
warn "Optional dependencies missing (needed for semantic search):"
for dep in "${missing_deps[@]}"; do
echo " - $dep"
done
echo ""
# Detect OS and show appropriate install command
case "$(uname -s)" in
Darwin)
info "Install on macOS:"
echo " brew install python3"
echo " pip3 install uvx"
;;
Linux)
info "Install on Linux:"
echo " sudo apt install python3 python3-pip"
echo " pip3 install uvx"
;;
MINGW*|MSYS*|CYGWIN*)
info "Install on Windows:"
echo " winget install Python.Python.3"
echo " pip install uvx"
;;
esac
echo ""
info "Note: Requires Python 3.13+. Most package managers install the latest version."
echo ""
info "Semantic search will be disabled until these are installed."
info "Core functionality (SQLite storage, full-text search) will work."
echo ""
else
success "Optional dependencies found (semantic search enabled)"
fi
}
# Main installation flow
main() {
local version="${1:-}"
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Claude Mnemonic - Installation Script ║"
echo "║ Persistent Memory System for Claude Code CLI ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
# Check required dependencies
if ! command -v curl &> /dev/null; then
error "curl is required but not installed"
fi
if ! command -v tar &> /dev/null; then
error "tar is required but not installed"
fi
# Detect platform
local platform
platform=$(detect_platform)
info "Detected platform: $platform"
# Get version
if [[ -z "$version" ]]; then
info "Fetching latest release..."
version=$(get_latest_version)
fi
info "Installing version: $version"
# Download and install
download_release "$version" "$platform"
# Register plugin
if register_plugin "$version"; then
success "Plugin registered successfully"
else
warn "Plugin registration incomplete - please install jq and run again"
fi
# Start worker
start_worker
# Check optional dependencies
check_optional_deps
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Installation Complete! ║"
echo "╠═══════════════════════════════════════════════════════════╣"
echo "║ Dashboard: http://localhost:37777 ║"
echo "║ Logs: /tmp/claude-mnemonic-worker.log ║"
echo "║ ║"
echo "║ Start a new Claude Code CLI session to activate memory. ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
}
# Handle --register-only flag
if [[ "${1:-}" == "--register-only" ]]; then
version=$(cat "$INSTALL_DIR/.claude-plugin/plugin.json" 2>/dev/null | grep '"version"' | sed -E 's/.*"([^"]+)".*/\1/' || echo "1.0.0")
register_plugin "v$version"
exit 0
fi
# Handle --uninstall flag
if [[ "${1:-}" == "--uninstall" ]]; then
KEEP_DATA=false
[[ "${2:-}" == "--keep-data" ]] && KEEP_DATA=true
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Claude Mnemonic - Uninstallation ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
info "Stopping worker processes..."
pkill -9 -f 'claude-mnemonic.*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
info "Removing plugin directories..."
rm -rf "$INSTALL_DIR"
rm -rf "$CACHE_DIR"
success "Plugin directories removed"
# Remove from JSON files (if jq is available)
if command -v jq &> /dev/null; then
info "Cleaning up Claude Code configuration..."
if [[ -f "$PLUGINS_FILE" ]]; then
jq 'del(.plugins["'"$PLUGIN_KEY"'"])' "$PLUGINS_FILE" > "${PLUGINS_FILE}.tmp" && mv "${PLUGINS_FILE}.tmp" "$PLUGINS_FILE"
fi
if [[ -f "$SETTINGS_FILE" ]]; then
jq 'del(.enabledPlugins["'"$PLUGIN_KEY"'"])' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" && mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
fi
if [[ -f "$MARKETPLACES_FILE" ]]; then
jq 'del(.["claude-mnemonic"])' "$MARKETPLACES_FILE" > "${MARKETPLACES_FILE}.tmp" && mv "${MARKETPLACES_FILE}.tmp" "$MARKETPLACES_FILE"
fi
success "Configuration cleaned up"
else
warn "jq not found - configuration files not cleaned up"
fi
# Handle data directory
DATA_DIR="$HOME/.claude-mnemonic"
if [[ -d "$DATA_DIR" ]]; then
if [[ "$KEEP_DATA" == "true" ]]; then
warn "Keeping data directory: $DATA_DIR"
else
info "Removing data directory..."
rm -rf "$DATA_DIR"
success "Data directory removed"
fi
fi
echo ""
success "Claude Mnemonic uninstalled successfully"
exit 0
fi
main "$@"
+94
View File
@@ -0,0 +1,94 @@
#!/bin/bash
# Register claude-mnemonic plugin with Claude Code
set -e
PLUGINS_FILE="$HOME/.claude/plugins/installed_plugins.json"
SETTINGS_FILE="$HOME/.claude/settings.json"
MARKETPLACES_FILE="$HOME/.claude/plugins/known_marketplaces.json"
PLUGIN_KEY="claude-mnemonic@claude-mnemonic"
MARKETPLACE_NAME="claude-mnemonic"
MARKETPLACE_PATH="$HOME/.claude/plugins/marketplaces/claude-mnemonic"
CACHE_PATH="$HOME/.claude/plugins/cache/claude-mnemonic/claude-mnemonic/1.0.0"
VERSION="1.0.0"
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%S.000Z")
# Ensure plugins directory exists
mkdir -p "$HOME/.claude/plugins"
# Create installed_plugins.json if it doesn't exist
if [ ! -f "$PLUGINS_FILE" ]; then
echo '{"version": 2, "plugins": {}}' > "$PLUGINS_FILE"
fi
# Create settings.json if it doesn't exist
if [ ! -f "$SETTINGS_FILE" ]; then
echo '{}' > "$SETTINGS_FILE"
fi
# Create known_marketplaces.json if it doesn't exist
if [ ! -f "$MARKETPLACES_FILE" ]; then
echo '{}' > "$MARKETPLACES_FILE"
fi
# Check if jq is available
if command -v jq &> /dev/null; then
# Ensure cache directory exists and copy plugin files
mkdir -p "$CACHE_PATH/.claude-plugin"
mkdir -p "$CACHE_PATH/hooks"
# Copy files from marketplace to cache
cp -r "$MARKETPLACE_PATH/"* "$CACHE_PATH/" 2>/dev/null || true
# Use jq for proper JSON manipulation
PLUGIN_ENTRY=$(cat <<EOF
[{
"scope": "user",
"installPath": "$CACHE_PATH",
"version": "$VERSION",
"installedAt": "$TIMESTAMP",
"lastUpdated": "$TIMESTAMP",
"isLocal": true
}]
EOF
)
# Add or update the plugin entry in installed_plugins.json
jq --arg key "$PLUGIN_KEY" --argjson entry "$PLUGIN_ENTRY" \
'.plugins[$key] = $entry' "$PLUGINS_FILE" > "${PLUGINS_FILE}.tmp" \
&& mv "${PLUGINS_FILE}.tmp" "$PLUGINS_FILE"
echo "Plugin registered in installed_plugins.json"
# Enable the plugin in settings.json
# First ensure enabledPlugins object exists, then add our plugin
jq --arg key "$PLUGIN_KEY" \
'.enabledPlugins //= {} | .enabledPlugins[$key] = true' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" \
&& mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
echo "Plugin enabled in settings.json"
# Register the marketplace in known_marketplaces.json
MARKETPLACE_ENTRY=$(cat <<EOF
{
"source": {
"source": "directory",
"path": "$MARKETPLACE_PATH"
},
"installLocation": "$MARKETPLACE_PATH",
"lastUpdated": "$TIMESTAMP"
}
EOF
)
jq --arg key "$MARKETPLACE_NAME" --argjson entry "$MARKETPLACE_ENTRY" \
'.[$key] = $entry' "$MARKETPLACES_FILE" > "${MARKETPLACES_FILE}.tmp" \
&& mv "${MARKETPLACES_FILE}.tmp" "$MARKETPLACES_FILE"
echo "Marketplace registered in known_marketplaces.json"
echo "Plugin registered successfully using jq"
else
echo "ERROR: jq is required for plugin registration"
echo "Please install jq: brew install jq (macOS) or apt-get install jq (Linux)"
exit 1
fi
+113
View File
@@ -0,0 +1,113 @@
# Claude Mnemonic - Windows Uninstallation Script
# Usage: irm https://raw.githubusercontent.com/lukaszraczylo/claude-mnemonic/main/scripts/uninstall.ps1 | iex
#
# Options:
# -KeepData Keep the data directory (~/.claude-mnemonic/)
# -Purge Remove everything including data (default)
param(
[switch]$KeepData,
[switch]$Purge
)
$ErrorActionPreference = "Stop"
# Configuration
$InstallDir = "$env:USERPROFILE\.claude\plugins\marketplaces\claude-mnemonic"
$CacheDir = "$env:USERPROFILE\.claude\plugins\cache\claude-mnemonic"
$DataDir = "$env:USERPROFILE\.claude-mnemonic"
$PluginsFile = "$env:USERPROFILE\.claude\plugins\installed_plugins.json"
$SettingsFile = "$env:USERPROFILE\.claude\settings.json"
$MarketplacesFile = "$env:USERPROFILE\.claude\plugins\known_marketplaces.json"
$PluginKey = "claude-mnemonic@claude-mnemonic"
function Write-Info { param($Message) Write-Host "[INFO] $Message" -ForegroundColor Blue }
function Write-Success { param($Message) Write-Host "[OK] $Message" -ForegroundColor Green }
function Write-Warn { param($Message) Write-Host "[WARN] $Message" -ForegroundColor Yellow }
Write-Host ""
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host " Claude Mnemonic - Windows Uninstallation Script " -ForegroundColor Cyan
Write-Host "================================================================" -ForegroundColor Cyan
Write-Host ""
# Stop worker processes
Write-Info "Stopping worker processes..."
Get-Process | Where-Object { $_.ProcessName -like "*worker*" -and $_.Path -like "*claude-mnemonic*" } | Stop-Process -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
Write-Success "Worker processes stopped"
# Remove plugin directories
Write-Info "Removing plugin directories..."
if (Test-Path $InstallDir) {
Remove-Item -Recurse -Force $InstallDir -ErrorAction SilentlyContinue
Write-Success "Removed $InstallDir"
} else {
Write-Info "Plugin directory not found (already removed)"
}
if (Test-Path $CacheDir) {
Remove-Item -Recurse -Force $CacheDir -ErrorAction SilentlyContinue
Write-Success "Removed $CacheDir"
}
# Remove from Claude Code configuration
Write-Info "Cleaning up Claude Code configuration..."
try {
if (Test-Path $PluginsFile) {
$Plugins = Get-Content $PluginsFile -Raw | ConvertFrom-Json
if ($Plugins.plugins.PSObject.Properties[$PluginKey]) {
$Plugins.plugins.PSObject.Properties.Remove($PluginKey)
$Plugins | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $PluginsFile
Write-Success "Removed from installed_plugins.json"
}
}
if (Test-Path $SettingsFile) {
$Settings = Get-Content $SettingsFile -Raw | ConvertFrom-Json
if ($Settings.enabledPlugins -and $Settings.enabledPlugins.PSObject.Properties[$PluginKey]) {
$Settings.enabledPlugins.PSObject.Properties.Remove($PluginKey)
$Settings | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $SettingsFile
Write-Success "Removed from settings.json"
}
}
if (Test-Path $MarketplacesFile) {
$Marketplaces = Get-Content $MarketplacesFile -Raw | ConvertFrom-Json
if ($Marketplaces.PSObject.Properties["claude-mnemonic"]) {
$Marketplaces.PSObject.Properties.Remove("claude-mnemonic")
$Marketplaces | ConvertTo-Json -Depth 10 | Out-File -Encoding UTF8 $MarketplacesFile
Write-Success "Removed from known_marketplaces.json"
}
}
} catch {
Write-Warn "Error cleaning up configuration files: $_"
}
# Handle data directory
if (Test-Path $DataDir) {
if ($KeepData) {
Write-Warn "Keeping data directory: $DataDir"
Write-Warn "To remove it later, run: Remove-Item -Recurse -Force $DataDir"
} else {
Write-Info "Removing data directory..."
Remove-Item -Recurse -Force $DataDir -ErrorAction SilentlyContinue
Write-Success "Removed $DataDir"
}
}
Write-Host ""
Write-Host "================================================================" -ForegroundColor Green
Write-Host " Uninstallation Complete! " -ForegroundColor Green
Write-Host "================================================================" -ForegroundColor Green
Write-Host ""
if ($KeepData) {
Write-Host " Data preserved at: $DataDir" -ForegroundColor White
Write-Host " To reinstall: irm .../install.ps1 | iex" -ForegroundColor White
Write-Host ""
}
Write-Success "Claude Mnemonic has been uninstalled"
+122
View File
@@ -0,0 +1,122 @@
#!/bin/bash
# Claude Mnemonic - Uninstallation Script
# Usage: curl -sSL https://raw.githubusercontent.com/lukaszraczylo/claude-mnemonic/main/scripts/uninstall.sh | bash
#
# Options:
# --keep-data Keep the data directory (~/.claude-mnemonic/)
# --purge Remove everything including data (default)
set -e
# Configuration
INSTALL_DIR="$HOME/.claude/plugins/marketplaces/claude-mnemonic"
CACHE_DIR="$HOME/.claude/plugins/cache/claude-mnemonic"
DATA_DIR="$HOME/.claude-mnemonic"
PLUGINS_FILE="$HOME/.claude/plugins/installed_plugins.json"
SETTINGS_FILE="$HOME/.claude/settings.json"
MARKETPLACES_FILE="$HOME/.claude/plugins/known_marketplaces.json"
PLUGIN_KEY="claude-mnemonic@claude-mnemonic"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
info() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[OK]${NC} $1"; }
warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
# Parse arguments
KEEP_DATA=false
for arg in "$@"; do
case $arg in
--keep-data)
KEEP_DATA=true
;;
--purge)
KEEP_DATA=false
;;
esac
done
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Claude Mnemonic - Uninstallation Script ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
# Stop worker
info "Stopping worker processes..."
pkill -9 -f 'claude-mnemonic.*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
success "Worker processes stopped"
# Remove plugin directories
info "Removing plugin directories..."
if [[ -d "$INSTALL_DIR" ]]; then
rm -rf "$INSTALL_DIR"
success "Removed $INSTALL_DIR"
else
info "Plugin directory not found (already removed)"
fi
if [[ -d "$CACHE_DIR" ]]; then
rm -rf "$CACHE_DIR"
success "Removed $CACHE_DIR"
fi
# Remove from Claude Code configuration (if jq is available)
if command -v jq &> /dev/null; then
info "Cleaning up Claude Code configuration..."
if [[ -f "$PLUGINS_FILE" ]]; then
jq 'del(.plugins["'"$PLUGIN_KEY"'"])' "$PLUGINS_FILE" > "${PLUGINS_FILE}.tmp" && mv "${PLUGINS_FILE}.tmp" "$PLUGINS_FILE"
success "Removed from installed_plugins.json"
fi
if [[ -f "$SETTINGS_FILE" ]]; then
jq 'del(.enabledPlugins["'"$PLUGIN_KEY"'"])' "$SETTINGS_FILE" > "${SETTINGS_FILE}.tmp" && mv "${SETTINGS_FILE}.tmp" "$SETTINGS_FILE"
success "Removed from settings.json"
fi
if [[ -f "$MARKETPLACES_FILE" ]]; then
jq 'del(.["claude-mnemonic"])' "$MARKETPLACES_FILE" > "${MARKETPLACES_FILE}.tmp" && mv "${MARKETPLACES_FILE}.tmp" "$MARKETPLACES_FILE"
success "Removed from known_marketplaces.json"
fi
else
warn "jq not found - Claude Code configuration files were not cleaned up"
warn "You may need to manually remove claude-mnemonic entries from:"
warn " - $PLUGINS_FILE"
warn " - $SETTINGS_FILE"
warn " - $MARKETPLACES_FILE"
fi
# Handle data directory
if [[ -d "$DATA_DIR" ]]; then
if [[ "$KEEP_DATA" == "true" ]]; then
warn "Keeping data directory: $DATA_DIR"
warn "To remove it later, run: rm -rf $DATA_DIR"
else
info "Removing data directory..."
rm -rf "$DATA_DIR"
success "Removed $DATA_DIR"
fi
fi
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ Uninstallation Complete! ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
if [[ "$KEEP_DATA" == "true" ]]; then
echo " Data preserved at: $DATA_DIR"
echo " To reinstall: curl -sSL .../install.sh | bash"
echo ""
fi
success "Claude Mnemonic has been uninstalled"
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# Unregister claude-mnemonic plugin from Claude Code
set -e
PLUGINS_FILE="$HOME/.claude/plugins/installed_plugins.json"
PLUGIN_KEY="claude-mnemonic@claude-mnemonic"
if [ ! -f "$PLUGINS_FILE" ]; then
echo "No plugins file found, nothing to unregister"
exit 0
fi
# Check if jq is available
if command -v jq &> /dev/null; then
# Use jq to remove the plugin entry
jq --arg key "$PLUGIN_KEY" 'del(.plugins[$key])' "$PLUGINS_FILE" > "${PLUGINS_FILE}.tmp" \
&& mv "${PLUGINS_FILE}.tmp" "$PLUGINS_FILE"
echo "Plugin unregistered successfully"
else
echo "Warning: jq not found, please manually remove $PLUGIN_KEY from $PLUGINS_FILE"
fi
+71
View File
@@ -0,0 +1,71 @@
#!/bin/bash
# Update marketplace.json with release checksums
# Called by goreleaser after release
set -e
VERSION="${1:-}"
CHECKSUMS_FILE="${2:-dist/checksums.txt}"
if [[ -z "$VERSION" ]]; then
echo "Usage: $0 <version> [checksums_file]"
exit 1
fi
if [[ ! -f "$CHECKSUMS_FILE" ]]; then
echo "Checksums file not found: $CHECKSUMS_FILE"
exit 1
fi
VERSION_TAG="v${VERSION}"
RELEASE_DATE=$(date -u +"%Y-%m-%d")
# Extract checksums
SHA_DARWIN_AMD64=$(grep "darwin_amd64" "$CHECKSUMS_FILE" | awk '{print $1}' || echo "")
SHA_DARWIN_ARM64=$(grep "darwin_arm64" "$CHECKSUMS_FILE" | awk '{print $1}' || echo "")
SHA_LINUX_AMD64=$(grep "linux_amd64" "$CHECKSUMS_FILE" | awk '{print $1}' || echo "")
SHA_WINDOWS_AMD64=$(grep "windows_amd64" "$CHECKSUMS_FILE" | awk '{print $1}' || echo "")
echo "Updating marketplace.json for ${VERSION_TAG}"
echo " darwin_amd64: ${SHA_DARWIN_AMD64:0:16}..."
echo " darwin_arm64: ${SHA_DARWIN_ARM64:0:16}..."
echo " linux_amd64: ${SHA_LINUX_AMD64:0:16}..."
echo " windows_amd64: ${SHA_WINDOWS_AMD64:0:16}..."
# Update marketplace.json
jq --arg v "$VERSION" \
--arg vt "$VERSION_TAG" \
--arg d "$RELEASE_DATE" \
--arg sha_da "$SHA_DARWIN_AMD64" \
--arg sha_dar "$SHA_DARWIN_ARM64" \
--arg sha_la "$SHA_LINUX_AMD64" \
--arg sha_wa "$SHA_WINDOWS_AMD64" \
'.plugins[0].version = $v |
.plugins[0].releases.latest = $v |
.plugins[0].releases.versions[$v] = {
"releaseDate": $d,
"downloads": {
"darwin-amd64": {
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/\($vt)/claude-mnemonic_\($v)_darwin_amd64.tar.gz",
"sha256": $sha_da,
"format": "tar.gz"
},
"darwin-arm64": {
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/\($vt)/claude-mnemonic_\($v)_darwin_arm64.tar.gz",
"sha256": $sha_dar,
"format": "tar.gz"
},
"linux-amd64": {
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/\($vt)/claude-mnemonic_\($v)_linux_amd64.tar.gz",
"sha256": $sha_la,
"format": "tar.gz"
},
"windows-amd64": {
"url": "https://github.com/lukaszraczylo/claude-mnemonic/releases/download/\($vt)/claude-mnemonic_\($v)_windows_amd64.zip",
"sha256": $sha_wa,
"format": "zip"
}
}
}' marketplace.json > marketplace.json.tmp && mv marketplace.json.tmp marketplace.json
echo "marketplace.json updated successfully"