Files
Andrew Yim 338176abbe feat: add D.intelligence Agent Corps (9 skills + shared infra)
Add 9 agent skills (#70-#77, #88) for D.intelligence business operations:
brand guardian, brand editor, doc secretary, quotation manager, service
architect, marketing manager, back office manager, account manager, and
skill update meta-agent. Includes shared Python package (dintel), reference
docs, document/quotation templates, service module CSVs, cross-device
installer, and comprehensive user guide.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 00:49:04 +09:00

652 lines
20 KiB
Bash
Executable File

#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────
# D.intelligence Agent Corps — Skill Bundle Installer
# Version: 1.0.0
# ─────────────────────────────────────────────────────────────────
#
# Installs the D.intelligence Agent Corps skill bundle for
# Claude Code and/or Claude Desktop on any macOS/Linux device.
#
# Usage:
# ./install.sh # Interactive mode
# ./install.sh --all # Install everything
# ./install.sh --code-only # Claude Code skills only
# ./install.sh --desktop-only # Claude Desktop skills only
# ./install.sh --dry-run # Preview without changes
# ./install.sh --uninstall # Remove installed skills
#
# Prerequisites:
# - Python >= 3.12
# - pip or uv (for Python dependencies)
# - Claude Code or Claude Desktop installed
# - Git (to clone the repository if not already present)
#
# ─────────────────────────────────────────────────────────────────
set -eu
# ── Constants ────────────────────────────────────────────────────
VERSION="1.0.0"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILLS_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
SHARED_DIR="$SCRIPT_DIR"
# Skill definitions: number|name|description
SKILLS=(
"70|dintel-brand-guardian|Brand compliance review & content generation"
"71|dintel-brand-editor|Brand-compliant copywriting & style evaluation"
"72|dintel-doc-secretary|Document formatting, meeting notes, reports"
"73|dintel-quotation-mgr|Quotation generation with multi-agent sub-system"
"74|dintel-service-architect|Service scope design & module recommendation"
"75|dintel-marketing-mgr|Marketing content pipeline management"
"76|dintel-backoffice-mgr|Administrative operations, invoicing, contracts"
"77|dintel-account-mgr|Client relationship management & monitoring"
"88|dintel-skill-update|Cross-skill consistency management (meta-agent)"
)
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m' # No Color
# ── Helper Functions ─────────────────────────────────────────────
log_info() { echo -e "${BLUE}[INFO]${NC} $*"; }
log_success() { echo -e "${GREEN}[OK]${NC} $*"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; }
log_error() { echo -e "${RED}[ERR]${NC} $*"; }
log_step() { echo -e "\n${BOLD}${CYAN}── $* ──${NC}"; }
DRY_RUN=false
INSTALL_CODE=false
INSTALL_DESKTOP=false
UNINSTALL=false
# ── Platform Detection ───────────────────────────────────────────
detect_platform() {
local os
os="$(uname -s)"
case "$os" in
Darwin) PLATFORM="macos" ;;
Linux) PLATFORM="linux" ;;
*) log_error "Unsupported platform: $os"; exit 1 ;;
esac
}
detect_claude_paths() {
# Claude Code config
CLAUDE_CODE_CONFIG="$HOME/.claude.json"
CLAUDE_CODE_DIR="$HOME/.claude"
# Claude Desktop config (platform-dependent)
if [[ "$PLATFORM" == "macos" ]]; then
CLAUDE_DESKTOP_CONFIG="$HOME/Library/Application Support/Claude/claude_desktop_config.json"
CLAUDE_DESKTOP_DIR="$HOME/Library/Application Support/Claude"
else
CLAUDE_DESKTOP_CONFIG="$HOME/.config/Claude/claude_desktop_config.json"
CLAUDE_DESKTOP_DIR="$HOME/.config/Claude"
fi
# Check which Claude products are installed
HAS_CLAUDE_CODE=false
HAS_CLAUDE_DESKTOP=false
if command -v claude &>/dev/null || [[ -f "$CLAUDE_CODE_CONFIG" ]]; then
HAS_CLAUDE_CODE=true
fi
if [[ -d "$CLAUDE_DESKTOP_DIR" ]]; then
HAS_CLAUDE_DESKTOP=true
fi
}
detect_python() {
PYTHON_CMD=""
for cmd in python3.13 python3.12 python3; do
if command -v "$cmd" &>/dev/null; then
local ver
ver="$($cmd --version 2>&1 | grep -oE '[0-9]+\.[0-9]+')"
local major minor
major="${ver%%.*}"
minor="${ver#*.}"
if [[ "$major" -ge 3 && "$minor" -ge 12 ]]; then
PYTHON_CMD="$cmd"
PYTHON_VERSION="$ver"
return
fi
fi
done
log_warn "Python >= 3.12 not found. Python utilities will not be installed."
}
detect_package_manager() {
PKG_MGR=""
if command -v uv &>/dev/null; then
PKG_MGR="uv"
elif command -v pip3 &>/dev/null; then
PKG_MGR="pip3"
elif command -v pip &>/dev/null; then
PKG_MGR="pip"
fi
}
# ── Parse Arguments ──────────────────────────────────────────────
parse_args() {
while [[ $# -gt 0 ]]; do
case "$1" in
--all)
INSTALL_CODE=true
INSTALL_DESKTOP=true
;;
--code-only)
INSTALL_CODE=true
;;
--desktop-only)
INSTALL_DESKTOP=true
;;
--dry-run)
DRY_RUN=true
;;
--uninstall)
UNINSTALL=true
;;
--help|-h)
show_help
exit 0
;;
*)
log_error "Unknown option: $1"
show_help
exit 1
;;
esac
shift
done
}
show_help() {
cat <<'HELP'
D.intelligence Agent Corps — Skill Bundle Installer v1.0.0
Usage:
./install.sh Interactive mode
./install.sh --all Install for both Claude Code and Desktop
./install.sh --code-only Claude Code only
./install.sh --desktop-only Claude Desktop only
./install.sh --dry-run Preview without making changes
./install.sh --uninstall Remove installed skills
Skills Included:
#70 Brand Guardian Brand compliance review
#71 Brand Editor Copywriting & style evaluation
#72 Doc Secretary Document formatting & reports
#73 Quotation Manager Quotation generation (multi-agent)
#74 Service Architect Service scope & module design
#75 Marketing Manager Content pipeline management
#76 Back Office Manager Admin, invoicing, contracts
#77 Account Manager Client relationship & monitoring
#88 Skill Update Cross-skill consistency (meta-agent)
Shared Infrastructure:
dintel-shared/ Python package + reference docs
HELP
}
# ── Pre-flight Checks ────────────────────────────────────────────
preflight() {
log_step "Pre-flight Checks"
detect_platform
log_info "Platform: $PLATFORM"
detect_claude_paths
if $HAS_CLAUDE_CODE; then
log_success "Claude Code detected"
else
log_warn "Claude Code not detected"
fi
if $HAS_CLAUDE_DESKTOP; then
log_success "Claude Desktop detected"
else
log_warn "Claude Desktop not detected"
fi
detect_python
if [[ -n "$PYTHON_CMD" ]]; then
log_success "Python $PYTHON_VERSION ($PYTHON_CMD)"
fi
detect_package_manager
if [[ -n "$PKG_MGR" ]]; then
log_success "Package manager: $PKG_MGR"
else
log_warn "No pip/uv found — skipping Python package install"
fi
# Verify skill directories exist
local missing=0
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
local dir="$SKILLS_ROOT/${num}-${name}"
if [[ ! -d "$dir" ]]; then
log_error "Missing skill directory: ${num}-${name}/"
((missing++))
fi
done
if [[ $missing -gt 0 ]]; then
log_error "$missing skill directories not found. Is the repository complete?"
exit 1
fi
log_success "All 9 skill directories present"
# Verify shared infrastructure
if [[ ! -f "$SHARED_DIR/pyproject.toml" ]]; then
log_error "dintel-shared/pyproject.toml not found"
exit 1
fi
if [[ ! -f "$SHARED_DIR/src/dintel/brand.py" ]]; then
log_error "dintel-shared/src/dintel/brand.py not found"
exit 1
fi
log_success "Shared infrastructure intact"
}
# ── Interactive Mode ─────────────────────────────────────────────
interactive_prompt() {
if $INSTALL_CODE || $INSTALL_DESKTOP || $UNINSTALL; then
return # Already specified via flags
fi
echo ""
echo -e "${BOLD}D.intelligence Agent Corps — Skill Bundle Installer v${VERSION}${NC}"
echo ""
echo " Available targets:"
if $HAS_CLAUDE_CODE; then
echo -e " ${GREEN}[1]${NC} Claude Code (code/CLAUDE.md directives)"
else
echo -e " ${RED}[1]${NC} Claude Code (not detected)"
fi
if $HAS_CLAUDE_DESKTOP; then
echo -e " ${GREEN}[2]${NC} Claude Desktop (desktop/SKILL.md skills)"
else
echo -e " ${RED}[2]${NC} Claude Desktop (not detected)"
fi
echo -e " ${GREEN}[3]${NC} Both"
echo ""
read -rp " Select target [1/2/3]: " choice
case "$choice" in
1) INSTALL_CODE=true ;;
2) INSTALL_DESKTOP=true ;;
3) INSTALL_CODE=true; INSTALL_DESKTOP=true ;;
*)
log_error "Invalid choice"
exit 1
;;
esac
}
# ── Install Python Environment ───────────────────────────────────
install_python_env() {
if [[ -z "$PYTHON_CMD" || -z "$PKG_MGR" ]]; then
log_warn "Skipping Python environment setup (missing Python or pip)"
return
fi
log_step "Python Environment — dintel-shared"
local venv_dir="$SHARED_DIR/.venv"
if $DRY_RUN; then
log_info "[DRY-RUN] Would create venv at: $venv_dir"
log_info "[DRY-RUN] Would install dintel package in editable mode"
return
fi
# Create virtual environment if it doesn't exist
if [[ ! -d "$venv_dir" ]]; then
log_info "Creating virtual environment..."
"$PYTHON_CMD" -m venv "$venv_dir"
log_success "Virtual environment created at $venv_dir"
else
log_info "Virtual environment already exists"
fi
# Activate and install
log_info "Installing dintel package (editable mode)..."
"$venv_dir/bin/pip" install --quiet --upgrade pip
"$venv_dir/bin/pip" install --quiet -e "$SHARED_DIR"
log_success "dintel package installed"
# Verify
if "$venv_dir/bin/python" -c "from dintel.brand import BRAND_NAME; print(f' Brand: {BRAND_NAME}')" 2>/dev/null; then
log_success "Package verification passed"
else
log_error "Package verification failed"
return 1
fi
}
# ── Install Claude Code Skills ───────────────────────────────────
install_code_skills() {
if ! $INSTALL_CODE; then return; fi
log_step "Claude Code Skills (code/CLAUDE.md)"
# Claude Code skills are activated by project CLAUDE.md includes.
# We create a project-level CLAUDE.md fragment that includes all skills.
local target_dir
if [[ -t 0 ]]; then
read -rp " Service Package repo path [default: current dir]: " target_dir
else
target_dir=""
fi
target_dir="${target_dir:-$(pwd)}"
# Resolve to absolute
target_dir="$(cd "$target_dir" 2>/dev/null && pwd)" || {
log_error "Invalid path: $target_dir"
return 1
}
local claude_md="$target_dir/CLAUDE.md"
local include_block=""
# Generate include block for CLAUDE.md
include_block+=$'\n'"# ── D.intelligence Agent Corps Skills ────────────────────────"$'\n'
include_block+="# Auto-generated by dintel-shared/install.sh v${VERSION}"$'\n'
include_block+="# Skills are loaded from: ${SKILLS_ROOT}"$'\n'
include_block+="#"$'\n'
include_block+="# To activate a specific agent in Claude Code, reference its CLAUDE.md:"$'\n'
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
local skill_claude_md="$SKILLS_ROOT/${num}-${name}/code/CLAUDE.md"
if [[ -f "$skill_claude_md" ]]; then
include_block+="# Agent #${num} (${name}): ${skill_claude_md}"$'\n'
fi
done
include_block+="# ─────────────────────────────────────────────────────────────"$'\n'
if $DRY_RUN; then
log_info "[DRY-RUN] Would append agent index to: $claude_md"
echo "$include_block"
return
fi
# Create symlinks in the project for easy access
local agents_dir="$target_dir/.claude-agents"
mkdir -p "$agents_dir"
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
local src="$SKILLS_ROOT/${num}-${name}/code/CLAUDE.md"
local dest="$agents_dir/${num}-${name}.md"
if [[ -f "$src" ]]; then
ln -sf "$src" "$dest"
log_success "#${num} ${name} → symlinked"
fi
done
# Symlink shared library
ln -sf "$SHARED_DIR" "$agents_dir/dintel-shared"
log_success "dintel-shared → symlinked"
# Write a loader CLAUDE.md fragment
cat > "$agents_dir/README.md" <<EOF
# D.intelligence Agent Corps — Claude Code
Symlinks to agent directives for Claude Code.
Generated by \`dintel-shared/install.sh v${VERSION}\`.
## Agents
| # | Agent | Directive |
|---|-------|-----------|
EOF
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
echo "| ${num} | ${name} | \`${num}-${name}.md\` |" >> "$agents_dir/README.md"
done
cat >> "$agents_dir/README.md" <<EOF
## Usage
In Claude Code, reference an agent directive:
\`\`\`
Read .claude-agents/70-dintel-brand-guardian.md
\`\`\`
Or add to your project CLAUDE.md as an include.
## Shared Library
\`dintel-shared/\` contains:
- \`src/dintel/brand.py\` — Brand constants, colors, service modules
- \`src/dintel/document.py\` — DOCX generation
- \`src/dintel/excel.py\` — Excel generation
- \`src/dintel/notion.py\` — Notion DB IDs
- \`references/\` — Brand guide, pricing, Notion schema, design system
EOF
log_success "Agent index created at $agents_dir/"
echo ""
log_info "To use agents in Claude Code:"
log_info " 1. cd $target_dir"
log_info " 2. claude (start Claude Code)"
log_info " 3. Reference .claude-agents/XX-name.md in your prompts"
}
# ── Install Claude Desktop Skills ────────────────────────────────
install_desktop_skills() {
if ! $INSTALL_DESKTOP; then return; fi
log_step "Claude Desktop Skills (desktop/SKILL.md)"
# Claude Desktop skills are stored as project knowledge files.
# They are loaded when the user opens a project that includes them.
local skills_target="$HOME/.claude/skills"
if $DRY_RUN; then
log_info "[DRY-RUN] Would create skill directory: $skills_target"
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
log_info "[DRY-RUN] Would symlink: ${num}-${name}/desktop/ → $skills_target/${num}-${name}/"
done
return
fi
mkdir -p "$skills_target"
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
local src="$SKILLS_ROOT/${num}-${name}/desktop"
local dest="$skills_target/${name}"
if [[ -d "$src" ]]; then
# Remove existing symlink/dir if present
rm -rf "$dest"
ln -sf "$src" "$dest"
log_success "#${num} ${name}$dest"
else
log_warn "#${num} ${name}: no desktop/ directory"
fi
done
# Symlink shared references
ln -sf "$SHARED_DIR/references" "$skills_target/dintel-references"
log_success "Shared references → $skills_target/dintel-references"
# Create an index file
cat > "$skills_target/dintel-index.md" <<EOF
# D.intelligence Agent Corps — Claude Desktop Skills
Installed by \`dintel-shared/install.sh v${VERSION}\`.
Source: \`${SKILLS_ROOT}\`
## Available Skills
| # | Skill | Description |
|---|-------|-------------|
EOF
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
echo "| ${num} | ${name} | ${desc} |" >> "$skills_target/INDEX.md"
done
cat >> "$skills_target/INDEX.md" <<EOF
## Usage in Claude Desktop
Add skill files as Project Knowledge when creating a new Claude Desktop project:
1. Open Claude Desktop → Settings → Projects
2. Create or open a D.intelligence project
3. Skills are auto-discovered from \`~/.claude/skills/dintel-*/SKILL.md\`
## Shared References
\`dintel-references/\` contains:
- \`dintelligence_brand_guide.md\` — Writing style guide
- \`design-system-2025.md\` — Visual identity system
- \`pricing-reference.md\` — Service pricing tables
- \`notion-schema-reference.md\` — Notion database schemas
EOF
log_success "Skill index created at $skills_target/INDEX.md"
echo ""
log_info "To use skills in Claude Desktop:"
log_info " 1. Open Claude Desktop → Projects"
log_info " 2. Skills are auto-registered as slash commands in Claude Code"
}
# ── Uninstall ────────────────────────────────────────────────────
uninstall() {
log_step "Uninstalling D.intelligence Agent Corps"
local skills_target="$HOME/.claude/skills"
local venv_dir="$SHARED_DIR/.venv"
if $DRY_RUN; then
log_info "[DRY-RUN] Would remove: $skills_target"
log_info "[DRY-RUN] Would remove: $venv_dir"
return
fi
if [[ -d "$skills_target" ]]; then
rm -rf "$skills_target"
log_success "Removed $skills_target"
else
log_info "No Desktop skills installed"
fi
if [[ -d "$venv_dir" ]]; then
rm -rf "$venv_dir"
log_success "Removed Python venv at $venv_dir"
else
log_info "No Python venv found"
fi
# Check for .claude-agents symlinks
# Don't auto-remove — user may have customized
if [[ -d ".claude-agents" ]]; then
log_warn "Found .claude-agents/ in current directory — remove manually if desired"
fi
log_success "Uninstall complete"
}
# ── Summary ──────────────────────────────────────────────────────
show_summary() {
log_step "Installation Summary"
echo ""
echo -e " ${BOLD}D.intelligence Agent Corps v${VERSION}${NC}"
echo -e " ─────────────────────────────────────────"
echo ""
if $INSTALL_CODE; then
echo -e " ${GREEN}${NC} Claude Code skills installed"
fi
if $INSTALL_DESKTOP; then
echo -e " ${GREEN}${NC} Claude Desktop skills installed"
fi
if [[ -n "$PYTHON_CMD" ]]; then
echo -e " ${GREEN}${NC} Python environment ready (dintel package)"
fi
echo ""
echo -e " ${BOLD}Agents:${NC}"
for entry in "${SKILLS[@]}"; do
IFS='|' read -r num name desc <<< "$entry"
echo -e " ${CYAN}#${num}${NC} ${name}${desc}"
done
echo ""
echo -e " ${BOLD}Shared Infrastructure:${NC}"
echo -e " ${CYAN}dintel-shared/${NC}"
echo " src/dintel/{brand,document,excel,notion}.py"
echo " references/{brand_guide,pricing,notion_schema,design_system}"
echo ""
echo -e " ${BOLD}Source:${NC} ${SKILLS_ROOT}"
echo ""
}
# ── Main ─────────────────────────────────────────────────────────
main() {
parse_args "$@"
echo ""
echo -e "${BOLD}╔══════════════════════════════════════════════════════════╗${NC}"
echo -e "${BOLD}║ D.intelligence Agent Corps — Skill Installer ║${NC}"
echo -e "${BOLD}║ v${VERSION} • 9 Agents + Shared Infrastructure ║${NC}"
echo -e "${BOLD}╚══════════════════════════════════════════════════════════╝${NC}"
if $DRY_RUN; then
echo -e "\n ${YELLOW}── DRY RUN MODE — No changes will be made ──${NC}\n"
fi
# Pre-flight
preflight
if $UNINSTALL; then
uninstall
exit 0
fi
# Interactive selection if no flags
interactive_prompt
# Install steps
install_python_env
install_code_skills
install_desktop_skills
# Summary
if ! $DRY_RUN; then
show_summary
fi
}
main "$@"