132 lines
4 KiB
Bash
132 lines
4 KiB
Bash
#!/bin/bash
|
|
# Agent Factory — export-system.sh
|
|
# Packages an agent system into a portable tarball with checksums.
|
|
# Usage: bash export-system.sh <export-name>
|
|
# Bash 3.2 compatible.
|
|
|
|
set -e
|
|
|
|
EXPORT_NAME="${1:-agent-system}"
|
|
DATE=$(python3 -c "import datetime; print(datetime.date.today().strftime('%Y-%m-%d'))")
|
|
OUTPUT_FILE="agent-system-${EXPORT_NAME}-${DATE}.tar.gz"
|
|
STAGING_DIR="/tmp/agent-export-$$"
|
|
MANIFEST_FILE="${STAGING_DIR}/MANIFEST.md"
|
|
|
|
# Determine project root (directory containing .claude/)
|
|
PROJECT_ROOT="$(pwd)"
|
|
if [ ! -d "${PROJECT_ROOT}/.claude" ]; then
|
|
echo "ERROR: No .claude/ directory found in $(pwd)" >&2
|
|
echo "Run this script from your project root." >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "[export] Starting export: ${EXPORT_NAME}"
|
|
echo "[export] Date: ${DATE}"
|
|
echo "[export] Output: ${OUTPUT_FILE}"
|
|
|
|
mkdir -p "${STAGING_DIR}"
|
|
|
|
# Collect files — explicit inclusions only
|
|
collect_files() {
|
|
local dir="$1"
|
|
local dest="$2"
|
|
if [ -d "${PROJECT_ROOT}/${dir}" ]; then
|
|
mkdir -p "${STAGING_DIR}/${dest}"
|
|
cp -r "${PROJECT_ROOT}/${dir}/." "${STAGING_DIR}/${dest}/" 2>/dev/null || true
|
|
echo "[export] Collected: ${dir}"
|
|
fi
|
|
}
|
|
|
|
collect_files ".claude/agents" ".claude/agents"
|
|
collect_files ".claude/skills" ".claude/skills"
|
|
collect_files ".claude/hooks" ".claude/hooks"
|
|
collect_files "hooks" "hooks"
|
|
collect_files "automation" "automation"
|
|
collect_files "scripts" "scripts"
|
|
|
|
# Copy settings.json if it exists
|
|
if [ -f "${PROJECT_ROOT}/.claude/settings.json" ]; then
|
|
mkdir -p "${STAGING_DIR}/.claude"
|
|
cp "${PROJECT_ROOT}/.claude/settings.json" "${STAGING_DIR}/.claude/settings.json"
|
|
echo "[export] Collected: .claude/settings.json"
|
|
fi
|
|
|
|
# Copy CLAUDE.md if it exists
|
|
if [ -f "${PROJECT_ROOT}/CLAUDE.md" ]; then
|
|
cp "${PROJECT_ROOT}/CLAUDE.md" "${STAGING_DIR}/CLAUDE.md"
|
|
echo "[export] Collected: CLAUDE.md"
|
|
fi
|
|
|
|
# Remove excluded files from staging
|
|
echo "[export] Removing excluded files"
|
|
rm -f "${STAGING_DIR}/.env" 2>/dev/null || true
|
|
find "${STAGING_DIR}" -name "*.local.*" -delete 2>/dev/null || true
|
|
find "${STAGING_DIR}" -name "audit.log" -delete 2>/dev/null || true
|
|
find "${STAGING_DIR}" -name "cost-events.jsonl" -delete 2>/dev/null || true
|
|
find "${STAGING_DIR}" -name ".git" -prune -o -print | grep "\.git$" | xargs rm -rf 2>/dev/null || true
|
|
rm -rf "${STAGING_DIR}/memory" 2>/dev/null || true
|
|
|
|
# Generate MANIFEST.md with checksums
|
|
echo "[export] Generating manifest"
|
|
|
|
COMPONENT_ROWS=""
|
|
find "${STAGING_DIR}" -type f | sort | while read -r fpath; do
|
|
rel="${fpath#${STAGING_DIR}/}"
|
|
checksum=$(python3 -c "import hashlib; print(hashlib.sha256(open('${fpath}','rb').read()).hexdigest()[:16])")
|
|
filetype="other"
|
|
case "$rel" in
|
|
.claude/agents/*) filetype="agent" ;;
|
|
.claude/skills/*) filetype="skill" ;;
|
|
.claude/hooks/*|hooks/*) filetype="hook" ;;
|
|
.claude/settings.json) filetype="settings" ;;
|
|
automation/*) filetype="automation" ;;
|
|
CLAUDE.md) filetype="context" ;;
|
|
esac
|
|
echo "| ${filetype} | ${rel} | ${checksum} |" >> "${MANIFEST_FILE}.rows"
|
|
done
|
|
|
|
cat > "${MANIFEST_FILE}" << MANIFEST
|
|
# Agent System Manifest
|
|
Export name: ${EXPORT_NAME}
|
|
Export date: ${DATE}
|
|
Generated by: Agent Factory export-system.sh
|
|
|
|
## Components
|
|
|
|
| Type | File | Checksum (SHA256, first 16) |
|
|
|------|------|---------------------------|
|
|
MANIFEST
|
|
|
|
if [ -f "${MANIFEST_FILE}.rows" ]; then
|
|
cat "${MANIFEST_FILE}.rows" >> "${MANIFEST_FILE}"
|
|
rm "${MANIFEST_FILE}.rows"
|
|
fi
|
|
|
|
cat >> "${MANIFEST_FILE}" << MANIFEST
|
|
|
|
## Requirements
|
|
|
|
| Requirement | Value |
|
|
|-------------|-------|
|
|
| Claude Code version | 1.x or later |
|
|
| MCP servers | List any required MCP servers here |
|
|
| Tools | List any required tools (Bash, WebSearch, etc.) |
|
|
| Environment | List required env vars (ANTHROPIC_API_KEY, etc.) |
|
|
|
|
## Notes
|
|
|
|
Add any project-specific setup notes here.
|
|
MANIFEST
|
|
|
|
echo "[export] Manifest written"
|
|
|
|
# Create tarball
|
|
cd "${STAGING_DIR}"
|
|
tar -czf "${PROJECT_ROOT}/${OUTPUT_FILE}" .
|
|
cd "${PROJECT_ROOT}"
|
|
|
|
# Cleanup
|
|
rm -rf "${STAGING_DIR}"
|
|
|
|
echo "[export] Done: ${OUTPUT_FILE}"
|
|
echo "[export] Size: $(du -sh "${OUTPUT_FILE}" | cut -f1)"
|