refactor(deploy): consolidate install scripts and INSTALL.md into deploy/

- Move scripts/install_mam.sh → deploy/install_mam.sh (local-clone installer)
- Move scripts/generate-env.sh → deploy/generate-env.sh (env helper)
- Move .agents/INSTALL.md → deploy/INSTALL.md (user manual)
- Update install_mam.sh to copy INSTALL.md + generate-env.sh from new paths
- Ship INSTALL.md via deploy/install.sh remote path too (manifest-tracked)
- Update README/BOOTSTRAP generate-env.sh references & repository ASCII layout
- Extend deploy/README.md structure section; extend gitea-ci.yml lint list
- Remove now-empty scripts/ directory
- Fix duplicate ### 2. subsection headers in deploy/README.md (address B-2)
- Correct deploy/INSTALL.md dependency description to match actual checks (address M-1)
- Add local-clone lifecycle caveat (no update.sh/remove.sh) (address M-2)

Closes the deploy consolidation plan and addresses Planner / Reviewer feedback.
This commit is contained in:
2026-07-12 16:30:15 +09:00
parent 2d2510f391
commit eb733cf7c1
10 changed files with 64 additions and 23 deletions
+108
View File
@@ -0,0 +1,108 @@
# 🛠️ Multi-Agent Mux (MAM) 설치 및 적용 가이드
MAM은 단일 워크스페이스 상에서 복수의 에이전트(Claude, Cline, Agy, Hermes 등)들이 서로의 상태를 오염시키지 않고 협업할 수 있도록 프로세스 격리 및 라이프사이클 관리를 제공하는 프레임워크입니다.
이 가이드는 기존의 다른 프로젝트/레포지토리에 MAM을 신속하게 도입하고 적용하는 절차를 설명합니다.
---
## 1. ⚙️ 사전 요구사항
MAM 스킬 및 스크립트들은 호스트 시스템의 다음 도구들에 의존합니다. 설치 전에 확인해 주세요.
* **tmux**: 에이전트를 백그라운드 격리 Pane에서 구동하기 위한 프로세스 컨테이너
* **python3**: 세션 레지스트리(YAML/SQLite DB) 파싱 및 유효성 검사 (내장 `sqlite3` 모듈 필수)
* **uuidgen**: 격리 세션 생성 시 고유의 UUID 할당
* **rsync**: 인스톨러(`deploy/install_mam.sh`)가 `.agents/` 오케스트레이터 및 스킬 폴더를 타겟 프로젝트에 복제하는 데 사용 (설치 시 필요)
* **python3-yaml (pyyaml)**: 세션 데이터 YAML 저장 및 로드 의존성 (`pip install pyyaml`)
---
## 2. 🚀 자동 설치 방법
MAM의 자동 설치 스크립트(`deploy/install_mam.sh`)를 사용하여 10초 만에 필요한 규칙과 라이프사이클 툴킷을 타겟 프로젝트에 이식할 수 있습니다. 스크립트는 실행 시 자동으로 시스템의 `tmux`, `python3`, `rsync`, `uuidgen` 및 필수 파이썬 모듈들을 진단합니다.
> [!IMPORTANT]
> **설치 전제조건**: MAM 스킬을 타겟 프로젝트에 설치하려면 **먼저 MAM 레포지토리가 로컬 머신에 clone 되어 있어야 합니다.**
### 설치 스크립트 실행
MAM 레포지토리 루트 디렉토리로 이동한 후 다음 명령어를 실행합니다.
```bash
# 기본 사용법 (타겟 프로젝트 경로 지정)
$ bash deploy/install_mam.sh --target /path/to/your/project
# 만약 이미 타겟에 AGENTS.md 가 존재하여 강제로 덮어쓰고 싶다면:
$ bash deploy/install_mam.sh --target /path/to/your/project --force
```
### 설치 스크립트가 수행하는 작업:
1. **의존성 진단**: 시스템에 `tmux`, `python3`, `rsync`, `uuidgen` CLI 바이너리와 파이썬 `pyyaml`/`sqlite3` 모듈이 설치되어 있는지 확인합니다.
2. **규칙 및 스킬 복제**: 오케스트레이션 가이드(`.agents/` 하위 전체)를 타겟 프로젝트 하위로 이식합니다.
3. **지침 전파**: 에이전트가 로드하고 복종할 행동 지침 문서(`AGENTS.md`)를 프로젝트 루트에 복사합니다.
4. **형상 제외 설정**: 세션 DB 및 격리 캐시 저장소인 `.mam/` 디렉토리를 타겟 프로젝트의 `.gitignore` 에 자동 주입하여 불필요한 형상 관리를 방지합니다.
---
## 3. 🎯 핵심 사용 워크플로우 (Quick Start)
설치가 완료되면, 타겟 프로젝트 루트에서 에이전트들을 기동 및 관리할 수 있습니다.
### 1) 에이전트 격리 세션 생성 (Create)
새로운 에이전트를 독립된 격리 가상 디렉토리에서 띄웁니다.
```bash
$ bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \
--workspace "/path/to/your/project" \
--agent claude \
--role developer \
--session my-project-dev-claude \
--isolate \
--tmux-server multi-agent-mux
```
* `--isolate` 옵션을 주면 `.mam/agent_homes/<uuid>/` 하위에 로그인 및 설정은 유지하되 대화 내역은 격리되는 홈이 형성됩니다.
### 2) 세션 접속 (Attach)
백그라운드에서 구동된 에이전트 TUI 화면에 들어갑니다. (세션 생성 시 지정한 독립 격리 tmux 서버 소켓 `-L multi-agent-mux` 를 경유해 접속합니다.)
```bash
$ tmux -L multi-agent-mux attach -t my-project-dev-claude
```
* **화면 탈출**: 대화 중 세션을 유지한 채 터미널로 돌아오려면 `Ctrl + B`를 누른 뒤 `D` 키를 차례로 입력합니다.
### 3) 에이전트 상태 복원 (Resume)
세션이 중지되었거나, 호스트 재기동으로 tmux가 소멸한 경우에도 이전 대화 ID 및 격리 디렉토리를 원자적으로 이어받아 다시 기동할 수 있습니다.
```bash
# 1단계: 복원 대상 세션의 UUID 자동 조회 (DB/YAML 레지스트리 기반)
$ WORKSPACE="/path/to/your/project"
$ AGENT="claude"
$ SESSION_NAME="my-project-dev-claude"
$ UUID=$(bash .agents/skills/multi-agent-mux-resume/scripts/resolve_session_id.sh \
--workspace "$WORKSPACE" --agent "$AGENT" --session "$SESSION_NAME")
# 복원 대상 세션의 유효성 검사 (M-1)
$ [ -n "$UUID" ] || { echo "[ERROR] 매칭되는 활성 세션 이력이 없습니다. create_session.sh를 통해 먼저 세션을 생성해 주세요."; exit 1; }
# 2단계: 세션 재기동 (이전 대화 컨텍스트 복원 기동)
# (주의: 만약 create 시 격리(--isolate) 세션으로 생성했다면, CLAUDE_CONFIG_DIR 환경변수를 YAML에 기록된 isolation.root 경로로 지정하여 띄워야 합니다. 상세 격리 복원 커맨드는 .agents/skills/multi-agent-mux-resume/SKILL.md 문서를 필독해 주세요.)
$ tmux -L multi-agent-mux new-session -d -s "$SESSION_NAME" -x 140 -y 40 -c "$WORKSPACE" \
"claude --dangerously-skip-permissions -r $UUID; echo 'CLAUDE EXIT'; bash"
# 3단계: 레지스트리 세션 상태를 running 으로 동기화 갱신
$ bash .agents/skills/multi-agent-mux-resume/scripts/update_yaml_resumed.sh \
--session "$SESSION_NAME" --uuid "$UUID" --agent "$AGENT"
```
### 4) 세션 종료 및 정리 (Stop / Purge)
세션을 정지시키고 대화 컨텍스트를 동결하거나(default), 완전히 소멸시킵니다(`--purge-conversation`).
```bash
# 대화 메타데이터를 백업 및 영속화하고, 안전하게 종료 (status=stopped)
$ bash .agents/skills/multi-agent-mux-stop/scripts/stop_session.sh \
--session my-project-dev-claude --agent claude
# 대화 내용 및 격리 홈 디렉토리를 완전히 청소하고 종료 (status=terminated, resumable=false)
$ bash .agents/skills/multi-agent-mux-stop/scripts/stop_session.sh \
--session my-project-dev-claude --agent claude --purge-conversation --yes
```
---
## 🛡️ 협업 및 보안 가이드라인
* MAM을 사용할 때 모든 에이전트(개발자, 리뷰어)들은 루트의 `AGENTS.md` 지침을 우선 숙지하도록 설계해야 오탐과 무분별한 리팩토링 범람을 방지할 수 있습니다.
* 각 에이전트 역할별로 리뷰 프로세스를 돌릴 시, 최종 승인 결과 보고서(.md)는 형상 관리가 추적할 수 있도록 버전 관리 대상 경로(구체적으로 `.agents/reports/<session_name>/` 또는 `docs/reports/` 등) 하위로 이관 복사하여 커밋하는 규약(`.agents/MULTI_AGENT_RULES.md`)을 준수해 주세요.
+16 -3
View File
@@ -6,7 +6,10 @@ This directory contains packaging templates and installation scripts to deploy t
## 📁 Deployment Directory Structure
* **`install.sh`**: A self-contained, idempotent shell installer that checks system requirements (`tmux`, `python3`, `pip3`), detects NFS/network filesystem mounts, sets up a local python virtual environment (`.venv`), and initializes environment configuration (`.env`).
* **`install.sh`**: A self-contained, idempotent remote shell installer (via curl) that checks system requirements (`tmux`, `python3`), detects NFS/network filesystem mounts, sets up a local python virtual environment (`.venv`), and initializes environment configuration (`.env`).
* **`install_mam.sh`**: A local-clone installer that copies rules/skills (`.agents/`), `AGENTS.md`, and sets up environment bootstrap on target projects.
* **`generate-env.sh`**: Environment configuration bootstrap helper.
* **`INSTALL.md`**: Detailed installation and quick-start user manual.
* **`plugin.json`**: Metadata declaration file to register MAM as an installable plugin for AI Agent coding platforms (such as Claude Code, Antigravity, or other TUI clients).
* **`gitea-ci.yml`**: CI/CD pipeline definition template for Gitea Actions (running ShellCheck linting on bash scripts, validation on python scripts, and compilation tests).
@@ -26,7 +29,17 @@ Alternatively, if they have cloned the repository, they can execute:
bash deploy/install.sh
```
### 2. Custom Fork / Private Mirror Installations
### 2. Local-Clone Installation
If you already have cloned this repository locally, you can port MAM to other local target projects:
```bash
bash deploy/install_mam.sh --target /path/to/your/project
```
Refer to **`INSTALL.md`** inside this directory for the full instructions and workflows.
> [!NOTE]
> The local-clone installer does not ship `update.sh`/`remove.sh` to targets. To enable in-place updates, re-run the remote installer (`curl ... | bash`) or copy `deploy/update.sh` + `deploy/remove.sh` manually.
### 3. Custom Fork / Private Mirror Installations
If you run a private mirror or fork, you can override the source URLs during installation using environment variables:
```bash
@@ -40,7 +53,7 @@ curl -fsSL https://my-mirror.example.com/.../install.sh \
MAM_INSTALLER_URL=https://my-mirror.example.com/.../install.sh bash deploy/update.sh
```
### 2. Registering as a Workspace Plugin
### 4. Registering as a Workspace Plugin
To register these skills globally or for a specific workspace:
* **Workspace Level**: Copy the `.agents/` folder into your project root.
* **Global Level (Gemini/Antigravity)**: Register the plugin path in your global config file at `~/.gemini/config/skills.json`:
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# generate-env.sh — create a local .env from the committed .env.example template.
#
# Behaviour:
# - .env absent → copy .env.example to .env, print the path.
# - .env present → no-op (leaves your edits intact), exit 0.
# - .env present --force → overwrite .env from .env.example (backs up to .env.bak).
#
# Paths are resolved relative to this script (repo root = parent of deploy/),
# so it works regardless of the caller's cwd.
#
# Usage: deploy/generate-env.sh [--force] [-h|--help]
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SRC="$REPO_ROOT/.env.example"
DST="$REPO_ROOT/.env"
FORCE=0
while [ $# -gt 0 ]; do
case "$1" in
--force) FORCE=1; shift ;;
-h|--help)
echo "Usage: $0 [--force]"
echo " Create .env from .env.example. --force overwrites an existing .env."
exit 0 ;;
*) echo "ERROR: unknown arg: $1" >&2; echo "Usage: $0 [--force]" >&2; exit 2 ;;
esac
done
[ -f "$SRC" ] || { echo "ERROR: template not found: $SRC" >&2; exit 1; }
if [ -f "$DST" ] && [ "$FORCE" != "1" ]; then
echo "no-op: $DST already exists (use --force to overwrite)"
exit 0
fi
if [ -f "$DST" ] && [ "$FORCE" = "1" ]; then
cp -p "$DST" "$DST.bak"
echo "backed up existing .env -> $DST.bak"
fi
cp "$SRC" "$DST"
echo "created: $DST"
echo "Next: edit $DST and fill in any secrets (look for 'replace_me')."
+4
View File
@@ -33,6 +33,10 @@ jobs:
shellcheck .agents/skills/multi-agent-mux-stop/scripts/stop_session.sh
shellcheck .agents/skills/multi-agent-mux-monitor/scripts/reconcile.sh
shellcheck deploy/install.sh
shellcheck deploy/install_mam.sh
shellcheck deploy/generate-env.sh
shellcheck deploy/update.sh
shellcheck deploy/remove.sh
echo "✅ ShellCheck completed successfully."
lint-python:
+9
View File
@@ -152,6 +152,15 @@ if ! check_assets_present "."; then
echo ".env.example" >> "$MANIFEST_FILE"
fi
# Ship the user manual into the target's .agents/ (consistent with install_mam.sh)
if [ -f "$STAGE_DIR/deploy/INSTALL.md" ]; then
mkdir -p .agents
if [ ! -e ".agents/INSTALL.md" ]; then
cp "$STAGE_DIR/deploy/INSTALL.md" .agents/INSTALL.md || { echo "❌ Error: Failed to copy INSTALL.md" >&2; exit 1; }
echo ".agents/INSTALL.md" >> "$MANIFEST_FILE"
fi
fi
rm -rf "$STAGE_DIR"
trap - EXIT
echo "✅ Skills staged into workspace (existing files preserved)."
+229
View File
@@ -0,0 +1,229 @@
#!/usr/bin/env bash
# ==============================================================================
# Multi-Agent Mux (MAM) Skill Installer
# Efficiently installs MAM orchestration rules & skills to another project.
# ==============================================================================
set -euo pipefail
# ANSI color codes
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Helper functions for logs
log_info() { echo -e "${BLUE}[INFO]${NC} $*"; }
log_ok() { echo -e "${GREEN}[OK]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
show_help() {
cat <<EOF
Usage: $0 [options]
Options:
-t, --target <path> Target directory/project where MAM should be installed (defaults to current directory)
-f, --force Force copy AGENTS.md even if it already exists (backups are still made)
-h, --help Show this help message
EOF
}
TARGET_DIR="."
FORCE=0
# Parse CLI arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-t|--target)
TARGET_DIR="$2"
shift 2
;;
-f|--force)
FORCE=1
shift
;;
-h|--help)
show_help
exit 0
;;
*)
log_error "Unknown option: $1"
show_help
exit 1
;;
esac
done
# Resolve absolute path for source and target, tracking symlinks gracefully
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SRC_DIR="$(cd "$DIR/.." && pwd)"
# Ensure target directory exists
if [ ! -d "$TARGET_DIR" ]; then
log_info "Creating target directory: $TARGET_DIR"
mkdir -p "$TARGET_DIR"
fi
TARGET_DIR="$(cd "$TARGET_DIR" && pwd)"
log_info "Installing MAM skills to target project: $TARGET_DIR"
log_info "Source directory resolved: $SRC_DIR"
if [ "$SRC_DIR" = "$TARGET_DIR" ]; then
log_error "Source and Target directories are the same! Cannot install to oneself."
exit 1
fi
# 1. Dependency Checks
log_info "Verifying host dependencies..."
DEPS=(tmux python3 rsync uuidgen)
MISSING_DEPS=()
for dep in "${DEPS[@]}"; do
if ! command -v "$dep" &>/dev/null; then
MISSING_DEPS+=("$dep")
fi
done
if [ ${#MISSING_DEPS[@]} -ne 0 ]; then
log_error "Missing required dependencies: ${MISSING_DEPS[*]}"
log_error "Please install them before using MAM."
exit 1
fi
# Check Python PyYAML and sqlite3 library (hard dependencies for registry parsing)
if ! python3 -c "import yaml, sqlite3" &>/dev/null; then
log_error "Python 'pyyaml' or built-in 'sqlite3' modules are missing (hard dependencies for session registry)."
log_error "Please run: pip install pyyaml"
exit 1
fi
log_ok "Dependency checks completed."
# 2. Copy .agents/ folder and config tools
log_info "Deploying orchestration rules & skills (.agents/)..."
mkdir -p "$TARGET_DIR/.agents"
# Sync rules and skills, avoiding copying temporary or system files
# Exclude git histories, reports, logs or internal runtime cache if any
rsync -a --exclude='.git/' --exclude='/reports/' --exclude='*.log' --exclude='__pycache__/' --exclude='*.pyc' "$SRC_DIR/.agents/" "$TARGET_DIR/.agents/"
log_ok "Deployed Rules and Skills under target's .agents/"
# Copy config templates and generate scripts (M-2)
if [ -f "$SRC_DIR/.env.example" ]; then
cp "$SRC_DIR/.env.example" "$TARGET_DIR/.env.example"
log_ok "Copied .env.example configuration template"
fi
if [ -f "$SRC_DIR/deploy/generate-env.sh" ]; then
mkdir -p "$TARGET_DIR/scripts"
cp "$SRC_DIR/deploy/generate-env.sh" "$TARGET_DIR/scripts/generate-env.sh"
chmod +x "$TARGET_DIR/scripts/generate-env.sh"
log_ok "Copied deploy/generate-env.sh helper tool"
fi
# Copy the user manual into the target's .agents/ (previously came via rsync of .agents/)
if [ -f "$SRC_DIR/deploy/INSTALL.md" ]; then
cp "$SRC_DIR/deploy/INSTALL.md" "$TARGET_DIR/.agents/INSTALL.md"
log_ok "Copied INSTALL.md user manual into target .agents/"
fi
# 3. Copy AGENTS.md to root or inject guidelines pointer
log_info "Configuring developer guidelines (AGENTS.md)..."
AGENTS_FILE="$TARGET_DIR/AGENTS.md"
MARKER_START="<!-- BEGIN MAM ORCHESTRATION -->"
MARKER_END="<!-- END MAM ORCHESTRATION -->"
if [ -f "$AGENTS_FILE" ]; then
if [ "$FORCE" -eq 1 ]; then
log_warn "AGENTS.md already exists in target project. Backing up and overwriting (--force)..."
cp "$AGENTS_FILE" "$AGENTS_FILE.bak.$(date +%s)"
cp "$SRC_DIR/AGENTS.md" "$AGENTS_FILE"
log_ok "Guidelines overwritten successfully."
else
if grep -Fq "$MARKER_START" "$AGENTS_FILE"; then
log_ok "MAM orchestration guidelines pointer already exists in AGENTS.md."
else
echo -e "\n$MARKER_START\n# 🤖 Multi-Agent Orchestration Guidelines\nPlease refer to [.agents/MULTI_AGENT_RULES.md](file://./.agents/MULTI_AGENT_RULES.md) for detailed collaborative rules and state flow constraints.\n$MARKER_END" >> "$AGENTS_FILE"
log_ok "Injected MAM guidelines pointer to existing AGENTS.md."
fi
fi
else
cp "$SRC_DIR/AGENTS.md" "$AGENTS_FILE"
log_ok "Guidelines AGENTS.md copied to project root."
fi
# 4. Gitignore adjustments
log_info "Registering runtime isolation blocks in .gitignore..."
GITIGNORE="$TARGET_DIR/.gitignore"
MAM_PATTERN="/.mam/"
VENV_PATTERN="/.venv/"
if [ -f "$GITIGNORE" ]; then
# Register .mam/ if absent
if grep -Eq '^/?\.mam/?$' "$GITIGNORE"; then
log_ok ".mam/ already registered in target's .gitignore."
else
echo -e "\n# Multi-Agent Mux (MAM) runtime databases and isolation cache\n$MAM_PATTERN" >> "$GITIGNORE"
log_ok "Appended /.mam/ registration to .gitignore."
fi
# Register .venv/ if absent
if grep -Eq '^/?\.venv/?$' "$GITIGNORE"; then
log_ok ".venv/ already registered in target's .gitignore."
else
echo -e "\n# Python virtual environment\n$VENV_PATTERN" >> "$GITIGNORE"
log_ok "Appended /.venv/ registration to .gitignore."
fi
else
echo -e "# Multi-Agent Mux (MAM) runtime databases and isolation cache\n$MAM_PATTERN\n\n# Python virtual environment\n$VENV_PATTERN" > "$GITIGNORE"
log_ok "Created .gitignore with MAM and .venv exclusions."
fi
# 5. Python Virtual Environment Setup (F-1)
log_info "Bootstrapping Python virtual environment (.venv) in target..."
VENV_NAME="$TARGET_DIR/.venv"
if [ ! -d "$VENV_NAME" ]; then
python3 -m venv "$VENV_NAME"
log_ok "Virtual environment created."
else
log_info "Virtual environment (.venv) already exists. Skipping creation."
fi
# Upgrade pip and install dependencies inside target venv
# shellcheck disable=SC1091
source "$VENV_NAME"/bin/activate
pip install --upgrade pip
REQ_FILE="$TARGET_DIR/.agents/skills/multi-agent-mux-delegate-job/requirements.txt"
if [ -f "$REQ_FILE" ]; then
log_info "Installing dependencies from $REQ_FILE..."
pip install -r "$REQ_FILE"
log_ok "Dependencies installed successfully."
else
log_warn "Could not find requirements file: $REQ_FILE. Installing defaults."
pip install "paho-mqtt>=2.0.0" pyyaml
fi
deactivate
# Done
log_ok "MAM Installation completed successfully!"
cat <<EOF
--------------------------------------------------------------------------------
💡 Quick Start Guide:
1. Initialize a new isolated session:
$ bash .agents/skills/multi-agent-mux-create/scripts/create_session.sh \\
--workspace "$TARGET_DIR" --agent claude --role developer --isolate \\
--tmux-server multi-agent-mux
2. Attach to the running session:
$ tmux -L multi-agent-mux attach -t <session_name>
3. Gracefully stop the session:
$ bash .agents/skills/multi-agent-mux-stop/scripts/stop_session.sh \\
--session <session_name> --agent claude
--------------------------------------------------------------------------------
EOF