Add automation scripts and sync memory files
Scripts added: - sync-memory.sh: Syncs Claude project memories to version control - cleanup-plans.sh: Archives old Claude plan files - scripts/README.md: Documentation for automation scripts Features: - Auto-sync mode for cron jobs - Dry-run mode for testing - Plan archival with timestamp preservation - Support for multiple hiveops projects Memory files synced: - dlx-ansible (141 lines) - hiveops-mgmt (45 lines) - hiveops-incident (15 lines) - hiveops-browser (25 lines) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
1d9896e6a1
commit
9f27515721
|
|
@ -0,0 +1,25 @@
|
||||||
|
# HiveOps Browser Project Memory
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
- **Browser**: Electron app at `/source/hiveops-src/hiveops-browser`
|
||||||
|
- **Mgmt Server**: Spring Boot at `/source/hiveops-src/hiveops-mgmt`
|
||||||
|
- IPC pattern: kebab-case channels (`get-config`), camelCase in preload (`getConfig`)
|
||||||
|
- API client returns `{ success, data }` or `{ success, error, status, code }`
|
||||||
|
- DTOs use Lombok `@Data @Builder @NoArgsConstructor @AllArgsConstructor`
|
||||||
|
- Services use `@RequiredArgsConstructor @Slf4j`, `@Transactional(readOnly=true)` for reads
|
||||||
|
- Controllers use `@RestController @RequestMapping("/api/v1/...")` with OpenAPI annotations
|
||||||
|
- Security: 3 filter chains (API@Order1, Portal@Order2, Default@Order3)
|
||||||
|
- Flyway migrations in `db/migration/`, H2 dev data in `db/h2/data.sql` (MERGE INTO syntax)
|
||||||
|
- H2 uses `CHAR(10)` for newlines (no `E'...\n...'` like PostgreSQL)
|
||||||
|
|
||||||
|
## Key Files
|
||||||
|
- `src/main/main.js` - Main process, IPC handlers, window management (~1400 lines)
|
||||||
|
- `src/main/api-client.js` - Axios-based API client
|
||||||
|
- `src/main/preload.js` - contextBridge IPC exposure
|
||||||
|
- Window pattern: check if exists, focus; else create BrowserWindow with preload
|
||||||
|
|
||||||
|
## Legal Content (Added Feb 2026)
|
||||||
|
- Legal API: `GET /api/v1/legal` and `GET /api/v1/legal/{section}` (public, no auth)
|
||||||
|
- 4 settings in `global_settings`: `legal.copyright`, `legal.license`, `legal.usagePolicy`, `legal.disclaimers`
|
||||||
|
- About page has tabbed layout: Info, License, Usage Policy, Disclaimers
|
||||||
|
- About window size: 650x700
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
# HiveOps Incident - Key Learnings
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
- Frontend: SvelteKit at `frontend/`, backend: Spring Boot at `backend/`
|
||||||
|
- CSS is split between standalone `.css` files (Dashboard, IncidentList, AtmHistory, JournalEvents, CreateIncident) and scoped `<style>` blocks in `.svelte` files (AtmProperties, IncidentWorkflow, MultiSelectDropdown, AtmInfoCard, AtmSelector)
|
||||||
|
- Global styles: `app.css` (`:root` vars) and `App.svelte` (global selectors with `:global()`)
|
||||||
|
|
||||||
|
## Typography System (implemented)
|
||||||
|
- All font sizes use CSS custom properties defined in `app.css :root`
|
||||||
|
- Variables: `--font-size-page-title` (1.4rem), `--font-size-section-title` (1.1rem), `--font-size-card-title` (0.95rem), `--font-size-body` (0.95rem), `--font-size-body-sm` (0.9rem), `--font-size-label` (0.85rem), `--font-size-caption` (0.8rem), `--font-size-tiny` (0.75rem), `--font-size-stat-value` (2rem), `--font-size-icon` (1.1rem), `--font-size-icon-sm` (0.9rem), `--font-size-subtitle` (0.85rem)
|
||||||
|
- `font-family` removed from `app.css` `:root`, kept in `App.svelte` global
|
||||||
|
|
||||||
|
## Build
|
||||||
|
- `cd frontend && npm run build` - quick (~2s), pre-existing unused CSS selector warnings in App.svelte dark mode styles are normal
|
||||||
|
- Git hosting: Gitea (not GitHub/GitLab)
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
# HiveOps Management Portal - Memory
|
||||||
|
|
||||||
|
## Admin Password Reset Feature
|
||||||
|
|
||||||
|
Successfully implemented admin password reset functionality for portal users.
|
||||||
|
|
||||||
|
### Key Implementation Details
|
||||||
|
|
||||||
|
**Backend Components:**
|
||||||
|
- `AuditLog.java`: Added USER_PASSWORD_RESET, USER_ENABLED, USER_DISABLED enum values
|
||||||
|
- `AuditService.java`: Added logPasswordReset(), logUserEnabled(), logUserDisabled() methods
|
||||||
|
- `UserRepository.java`: Added search() method with JPQL query for email/name search
|
||||||
|
- `ResetPasswordRequest.java`: DTO with password validation (min 8, max 100 chars)
|
||||||
|
- `UserService.java`: Enhanced with findAll(), searchUsers(), resetPassword(), enableUser(), disableUser()
|
||||||
|
- `PortalUserController.java`: New controller at /portal/users with ADMIN role authorization
|
||||||
|
- `SecurityConfig.java`: Added authorization rule for /portal/users/** requiring ADMIN role
|
||||||
|
|
||||||
|
**Frontend Components:**
|
||||||
|
- `list.html`: User list with search, role filter, and pagination
|
||||||
|
- `view.html`: User details with action buttons (reset password, enable/disable)
|
||||||
|
- `reset-password.html`: Password reset form with validation
|
||||||
|
- `base.html`: Added Users menu item in sidebar (ADMIN only)
|
||||||
|
|
||||||
|
### Security Patterns
|
||||||
|
- BCrypt password encoding (strength 12)
|
||||||
|
- @PreAuthorize("hasRole('ADMIN')") on controller
|
||||||
|
- Prevents admin from disabling own account
|
||||||
|
- All actions logged to audit_logs table with admin email, target user email, and IP address
|
||||||
|
|
||||||
|
### Common Patterns in Portal
|
||||||
|
- Flash messages via RedirectAttributes (success/error)
|
||||||
|
- getClientIp() helper extracts IP from X-Forwarded-For or remote address
|
||||||
|
- Pagination with PageRequest.of(page, size, Sort)
|
||||||
|
- Bootstrap 5 styling with badges for status/role
|
||||||
|
- Thymeleaf validation with .invalid-feedback for errors
|
||||||
|
|
||||||
|
### Testing Checklist
|
||||||
|
1. Login as admin@directlx.dev / admin123
|
||||||
|
2. Navigate to Users menu (visible to ADMIN only)
|
||||||
|
3. Search users by email/name
|
||||||
|
4. View user details
|
||||||
|
5. Reset password (validate min 8 chars, matching confirmation)
|
||||||
|
6. Enable/disable user (cannot disable self)
|
||||||
|
7. Verify audit log entries created
|
||||||
|
8. Test login with new password
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
# Scripts Directory
|
||||||
|
|
||||||
|
Automation scripts for managing Claude configurations and memory.
|
||||||
|
|
||||||
|
## sync-memory.sh
|
||||||
|
|
||||||
|
Synchronizes Claude's in-memory project knowledge to this version-controlled repository.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Interactive sync with commit prompt
|
||||||
|
./scripts/sync-memory.sh
|
||||||
|
|
||||||
|
# Auto-commit with timestamp
|
||||||
|
./scripts/sync-memory.sh --auto
|
||||||
|
|
||||||
|
# Preview changes without modifying files
|
||||||
|
./scripts/sync-memory.sh --dry-run
|
||||||
|
```
|
||||||
|
|
||||||
|
### What It Syncs
|
||||||
|
|
||||||
|
- `~/.claude/projects/-source-dlx-src-dlx-ansible/memory/MEMORY.md` → `memory/dlx-ansible/MEMORY.md`
|
||||||
|
- `~/.claude/projects/-source-hiveops-src-hiveops-mgmt/memory/MEMORY.md` → `memory/hiveops-mgmt/MEMORY.md`
|
||||||
|
- `~/.claude/projects/-source-hiveops-src-hiveops-incident/memory/MEMORY.md` → `memory/hiveops-incident/MEMORY.md`
|
||||||
|
- `~/.claude/projects/-source-hiveops-src-hiveops-browser/memory/MEMORY.md` → `memory/hiveops-browser/MEMORY.md`
|
||||||
|
|
||||||
|
### Automatic Syncing
|
||||||
|
|
||||||
|
#### Option 1: Cron Job (Scheduled)
|
||||||
|
|
||||||
|
Run sync every day at 2 AM:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Add to crontab
|
||||||
|
crontab -e
|
||||||
|
|
||||||
|
# Add this line:
|
||||||
|
0 2 * * * cd /source/dlx-src/dlx-claude && ./scripts/sync-memory.sh --auto && git push origin main 2>&1 | logger -t claude-sync
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 2: Git Hook (On Commit)
|
||||||
|
|
||||||
|
Create a post-commit hook in projects to trigger sync:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# In ~/.claude/hooks/ (if Claude supports this)
|
||||||
|
# Or manually run after significant work sessions
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Option 3: Manual (Recommended)
|
||||||
|
|
||||||
|
Run manually after completing significant work:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /source/dlx-src/dlx-claude
|
||||||
|
./scripts/sync-memory.sh
|
||||||
|
git push origin main
|
||||||
|
```
|
||||||
|
|
||||||
|
### Workflow
|
||||||
|
|
||||||
|
1. Work with Claude Code on infrastructure projects
|
||||||
|
2. Claude updates memory files in `~/.claude/projects/`
|
||||||
|
3. Run sync script to version control knowledge
|
||||||
|
4. Push to Gitea for team sharing and backup
|
||||||
|
|
||||||
|
### Best Practices
|
||||||
|
|
||||||
|
- Run sync after completing major tasks
|
||||||
|
- Review changes before committing (use interactive mode)
|
||||||
|
- Use `--dry-run` to preview changes first
|
||||||
|
- Keep memory files under 200 lines (Claude's limit)
|
||||||
|
- Document critical learnings immediately
|
||||||
|
|
||||||
|
## cleanup-plans.sh
|
||||||
|
|
||||||
|
Manages Claude's plan files by archiving old plans to keep the directory clean.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all plan files with ages
|
||||||
|
./scripts/cleanup-plans.sh
|
||||||
|
|
||||||
|
# Archive plans older than 30 days
|
||||||
|
./scripts/cleanup-plans.sh --archive
|
||||||
|
|
||||||
|
# Archive all plans
|
||||||
|
./scripts/cleanup-plans.sh --archive-all
|
||||||
|
|
||||||
|
# Change age threshold (e.g., 60 days)
|
||||||
|
./scripts/cleanup-plans.sh --archive --days 60
|
||||||
|
```
|
||||||
|
|
||||||
|
### What It Does
|
||||||
|
|
||||||
|
Claude Code creates plan files in `~/.claude/plans/` for each planning session. Over time, these accumulate. This script:
|
||||||
|
|
||||||
|
1. Lists all plan files with their ages
|
||||||
|
2. Identifies plans older than a threshold (default: 30 days)
|
||||||
|
3. Archives old plans to `~/.claude/plans-archive/YYYY-MM-DD/`
|
||||||
|
4. Preserves recent plans in the active directory
|
||||||
|
|
||||||
|
### When to Use
|
||||||
|
|
||||||
|
- Monthly cleanup: Archive plans older than 30 days
|
||||||
|
- Project cleanup: Archive all plans when starting fresh
|
||||||
|
- Regular maintenance: Keep the plans directory manageable
|
||||||
|
|
||||||
|
### Archive Location
|
||||||
|
|
||||||
|
Archived plans are moved to: `~/.claude/plans-archive/YYYY-MM-DD/`
|
||||||
|
|
||||||
|
This preserves plans by archive date, allowing you to:
|
||||||
|
- Reference old planning sessions if needed
|
||||||
|
- Restore plans if accidentally archived
|
||||||
|
- Delete archive folders when truly no longer needed
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Created**: 2026-02-09
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# cleanup-plans.sh - Archive old Claude plan files
|
||||||
|
#
|
||||||
|
# Claude Code creates plan files in ~/.claude/plans/ for each planning session.
|
||||||
|
# This script helps manage these files by archiving old plans to keep the directory clean.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/cleanup-plans.sh # List plans and show what would be archived
|
||||||
|
# ./scripts/cleanup-plans.sh --archive # Archive plans older than 30 days
|
||||||
|
# ./scripts/cleanup-plans.sh --archive-all # Archive all plans
|
||||||
|
# ./scripts/cleanup-plans.sh --days 60 # Change age threshold (default: 30)
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PLANS_DIR="$HOME/.claude/plans"
|
||||||
|
ARCHIVE_DIR="$HOME/.claude/plans-archive"
|
||||||
|
DAYS_OLD=30
|
||||||
|
ACTION="list"
|
||||||
|
|
||||||
|
# Color output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case $1 in
|
||||||
|
--archive)
|
||||||
|
ACTION="archive"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--archive-all)
|
||||||
|
ACTION="archive_all"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--days)
|
||||||
|
DAYS_OLD="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $1"
|
||||||
|
echo "Usage: $0 [--archive] [--archive-all] [--days N]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BLUE}║ Claude Plan Files Cleanup ║${NC}"
|
||||||
|
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Check if plans directory exists
|
||||||
|
if [ ! -d "$PLANS_DIR" ]; then
|
||||||
|
echo -e "${YELLOW}No plans directory found at: $PLANS_DIR${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count files
|
||||||
|
TOTAL_COUNT=$(find "$PLANS_DIR" -type f -name "*.md" | wc -l)
|
||||||
|
echo -e "Total plan files: ${GREEN}$TOTAL_COUNT${NC}"
|
||||||
|
|
||||||
|
if [ $TOTAL_COUNT -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}No plan files to clean up.${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Find old files
|
||||||
|
if [ "$ACTION" = "archive_all" ]; then
|
||||||
|
OLD_FILES=$(find "$PLANS_DIR" -type f -name "*.md")
|
||||||
|
OLD_COUNT=$TOTAL_COUNT
|
||||||
|
else
|
||||||
|
OLD_FILES=$(find "$PLANS_DIR" -type f -name "*.md" -mtime +$DAYS_OLD)
|
||||||
|
if [ -z "$OLD_FILES" ]; then
|
||||||
|
OLD_COUNT=0
|
||||||
|
else
|
||||||
|
OLD_COUNT=$(echo "$OLD_FILES" | wc -l)
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
RECENT_COUNT=$((TOTAL_COUNT - OLD_COUNT))
|
||||||
|
|
||||||
|
echo -e "Plans older than $DAYS_OLD days: ${YELLOW}$OLD_COUNT${NC}"
|
||||||
|
echo -e "Recent plans: ${GREEN}$RECENT_COUNT${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# List mode
|
||||||
|
if [ "$ACTION" = "list" ]; then
|
||||||
|
echo -e "${BLUE}Plan Files by Age:${NC}"
|
||||||
|
echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
|
||||||
|
# List all files sorted by modification time
|
||||||
|
find "$PLANS_DIR" -type f -name "*.md" -printf "%T+ %p\n" | sort -r | while read -r line; do
|
||||||
|
timestamp=$(echo "$line" | cut -d' ' -f1 | cut -d'+' -f1)
|
||||||
|
filepath=$(echo "$line" | cut -d' ' -f2-)
|
||||||
|
filename=$(basename "$filepath")
|
||||||
|
|
||||||
|
# Calculate age in days
|
||||||
|
file_time=$(stat -c %Y "$filepath")
|
||||||
|
current_time=$(date +%s)
|
||||||
|
age_days=$(( (current_time - file_time) / 86400 ))
|
||||||
|
|
||||||
|
if [ $age_days -gt $DAYS_OLD ]; then
|
||||||
|
echo -e "${YELLOW}📄${NC} $timestamp $filename (${age_days}d old)"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}📄${NC} $timestamp $filename (${age_days}d old)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}To archive old plans, run:${NC}"
|
||||||
|
echo -e " ./scripts/cleanup-plans.sh --archive"
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}To archive all plans, run:${NC}"
|
||||||
|
echo -e " ./scripts/cleanup-plans.sh --archive-all"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Archive mode
|
||||||
|
if [ "$ACTION" = "archive" ] || [ "$ACTION" = "archive_all" ]; then
|
||||||
|
if [ $OLD_COUNT -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}No old plan files to archive.${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create archive directory with timestamp
|
||||||
|
TIMESTAMP=$(date '+%Y-%m-%d')
|
||||||
|
ARCHIVE_PATH="$ARCHIVE_DIR/$TIMESTAMP"
|
||||||
|
mkdir -p "$ARCHIVE_PATH"
|
||||||
|
|
||||||
|
echo -e "${BLUE}Archiving $OLD_COUNT plan files to:${NC}"
|
||||||
|
echo -e " $ARCHIVE_PATH"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Move files
|
||||||
|
ARCHIVED=0
|
||||||
|
echo "$OLD_FILES" | while read -r filepath; do
|
||||||
|
if [ -f "$filepath" ]; then
|
||||||
|
filename=$(basename "$filepath")
|
||||||
|
mv "$filepath" "$ARCHIVE_PATH/"
|
||||||
|
echo -e "${GREEN}✓${NC} Archived: $filename"
|
||||||
|
ARCHIVED=$((ARCHIVED + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo -e "Archived: $OLD_COUNT files"
|
||||||
|
echo -e "Archive location: $ARCHIVE_PATH"
|
||||||
|
echo -e "Remaining: $RECENT_COUNT files"
|
||||||
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}Cleanup complete!${NC}"
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,182 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# sync-memory.sh - Sync Claude memory files to dlx-claude repository
|
||||||
|
#
|
||||||
|
# This script copies Claude's in-memory project knowledge to the version-controlled
|
||||||
|
# dlx-claude repository for backup and team sharing.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./scripts/sync-memory.sh # Interactive sync with git commit
|
||||||
|
# ./scripts/sync-memory.sh --auto # Auto-commit with timestamp
|
||||||
|
# ./scripts/sync-memory.sh --dry-run # Preview changes only
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||||
|
CLAUDE_HOME="$HOME/.claude"
|
||||||
|
|
||||||
|
# Color output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
DRY_RUN=false
|
||||||
|
AUTO_COMMIT=false
|
||||||
|
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
--dry-run)
|
||||||
|
DRY_RUN=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--auto)
|
||||||
|
AUTO_COMMIT=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown option: $arg"
|
||||||
|
echo "Usage: $0 [--dry-run] [--auto]"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${BLUE}╔════════════════════════════════════════════════════════════════╗${NC}"
|
||||||
|
echo -e "${BLUE}║ Claude Memory Sync to dlx-claude Repository ║${NC}"
|
||||||
|
echo -e "${BLUE}╚════════════════════════════════════════════════════════════════╝${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Define sync mappings: source -> destination
|
||||||
|
declare -A SYNC_MAP=(
|
||||||
|
["$CLAUDE_HOME/projects/-source-dlx-src-dlx-ansible/memory/MEMORY.md"]="$REPO_ROOT/memory/dlx-ansible/MEMORY.md"
|
||||||
|
["$CLAUDE_HOME/projects/-source-hiveops-src-hiveops-mgmt/memory/MEMORY.md"]="$REPO_ROOT/memory/hiveops-mgmt/MEMORY.md"
|
||||||
|
["$CLAUDE_HOME/projects/-source-hiveops-src-hiveops-incident/memory/MEMORY.md"]="$REPO_ROOT/memory/hiveops-incident/MEMORY.md"
|
||||||
|
["$CLAUDE_HOME/projects/-source-hiveops-src-hiveops-browser/memory/MEMORY.md"]="$REPO_ROOT/memory/hiveops-browser/MEMORY.md"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check if running in dry-run mode
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo -e "${YELLOW}[DRY RUN MODE]${NC} No files will be modified."
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync files
|
||||||
|
SYNCED_COUNT=0
|
||||||
|
SKIPPED_COUNT=0
|
||||||
|
CHANGED_FILES=()
|
||||||
|
|
||||||
|
for source in "${!SYNC_MAP[@]}"; do
|
||||||
|
dest="${SYNC_MAP[$source]}"
|
||||||
|
|
||||||
|
if [ ! -f "$source" ]; then
|
||||||
|
echo -e "${YELLOW}⊘${NC} Skipped (source not found): $(basename "$source")"
|
||||||
|
SKIPPED_COUNT=$((SKIPPED_COUNT + 1))
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create destination directory if needed
|
||||||
|
dest_dir="$(dirname "$dest")"
|
||||||
|
if [ "$DRY_RUN" = false ]; then
|
||||||
|
mkdir -p "$dest_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if files differ
|
||||||
|
if [ -f "$dest" ] && cmp -s "$source" "$dest"; then
|
||||||
|
echo -e "${GREEN}✓${NC} No changes: $(basename "$source")"
|
||||||
|
else
|
||||||
|
if [ "$DRY_RUN" = false ]; then
|
||||||
|
cp "$source" "$dest"
|
||||||
|
echo -e "${GREEN}✓${NC} Synced: $(basename "$source")"
|
||||||
|
CHANGED_FILES+=("$dest")
|
||||||
|
else
|
||||||
|
echo -e "${BLUE}~${NC} Would sync: $(basename "$source")"
|
||||||
|
fi
|
||||||
|
SYNCED_COUNT=$((SYNCED_COUNT + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo -e "Files synced: $SYNCED_COUNT"
|
||||||
|
echo -e "Files skipped: $SKIPPED_COUNT"
|
||||||
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Exit if dry-run or no changes
|
||||||
|
if [ "$DRY_RUN" = true ]; then
|
||||||
|
echo -e "${YELLOW}Dry run complete. No files were modified.${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $SYNCED_COUNT -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}All memory files are up to date. Nothing to commit.${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Git operations
|
||||||
|
cd "$REPO_ROOT"
|
||||||
|
|
||||||
|
# Check if we're in a git repository
|
||||||
|
if [ ! -d ".git" ]; then
|
||||||
|
echo -e "${RED}Error: Not a git repository: $REPO_ROOT${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Stage changed files
|
||||||
|
echo -e "${BLUE}Staging changed files...${NC}"
|
||||||
|
for file in "${CHANGED_FILES[@]}"; do
|
||||||
|
git add "$file"
|
||||||
|
echo " + $(git diff --cached --stat "$file" | head -1)"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Show git status
|
||||||
|
echo
|
||||||
|
echo -e "${BLUE}Git status:${NC}"
|
||||||
|
git status --short
|
||||||
|
|
||||||
|
# Commit changes
|
||||||
|
if [ "$AUTO_COMMIT" = true ]; then
|
||||||
|
# Auto-commit with timestamp
|
||||||
|
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')
|
||||||
|
git commit -m "Auto-sync Claude memory files - $TIMESTAMP
|
||||||
|
|
||||||
|
Updated memory files:
|
||||||
|
$(for file in "${CHANGED_FILES[@]}"; do echo " - $(basename "$file")"; done)
|
||||||
|
|
||||||
|
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}✓ Changes committed automatically${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}Push to remote:${NC}"
|
||||||
|
echo " git push origin main"
|
||||||
|
else
|
||||||
|
# Interactive commit
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}Ready to commit changes.${NC}"
|
||||||
|
echo
|
||||||
|
read -p "Commit message (or Enter for default): " COMMIT_MSG
|
||||||
|
|
||||||
|
if [ -z "$COMMIT_MSG" ]; then
|
||||||
|
COMMIT_MSG="Sync Claude memory files
|
||||||
|
|
||||||
|
Updated memory files:
|
||||||
|
$(for file in "${CHANGED_FILES[@]}"; do echo " - $(basename "$file")"; done)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git commit -m "$COMMIT_MSG
|
||||||
|
|
||||||
|
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}✓ Changes committed${NC}"
|
||||||
|
echo
|
||||||
|
echo -e "${YELLOW}Push to remote:${NC}"
|
||||||
|
echo " git push origin main"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo -e "${GREEN}Memory sync complete!${NC}"
|
||||||
Loading…
Reference in New Issue