191 lines
4.6 KiB
Bash
191 lines
4.6 KiB
Bash
#!/bin/bash
|
|
set -e
|
|
|
|
SKILLS_DIR="${SKILLS_DIR:-/skills}"
|
|
SKILL_DIR="$(dirname "$(dirname "$0")")"
|
|
|
|
# Install Node.js (required for Claude CLI)
|
|
install_node() {
|
|
if command -v node &>/dev/null; then
|
|
echo "Node.js already installed: $(node --version)"
|
|
return 0
|
|
fi
|
|
|
|
echo "Installing Node.js..."
|
|
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -
|
|
apt-get install -y nodejs
|
|
|
|
echo "Node.js installed: $(node --version)"
|
|
}
|
|
|
|
# Install Claude Code CLI
|
|
install_claude() {
|
|
if command -v claude &>/dev/null; then
|
|
echo "Claude CLI already installed: $(claude --version)"
|
|
return 0
|
|
fi
|
|
|
|
echo "Installing Claude Code CLI..."
|
|
npm install -g @anthropic-ai/claude-code
|
|
|
|
echo "Claude CLI installed: $(claude --version)"
|
|
}
|
|
|
|
# Install socat for HTTP server
|
|
install_deps() {
|
|
if command -v socat &>/dev/null && command -v jq &>/dev/null; then
|
|
return 0
|
|
fi
|
|
|
|
echo "Installing dependencies..."
|
|
apt-get update && apt-get install -y socat jq
|
|
}
|
|
|
|
# Generate system prompt with skills context
|
|
generate_system_prompt() {
|
|
local prompt_file="$SKILL_DIR/prompts/system.md"
|
|
|
|
cat > "$prompt_file" << 'EOF'
|
|
# VibeStack Agent
|
|
|
|
You are an autonomous agent running inside a VibeStack skill-based container. You have full access to the system and can modify skills.
|
|
|
|
## Environment
|
|
|
|
- Skills directory: /skills
|
|
- Each skill is a separate Git repository
|
|
- Skills have: SKILL.md (metadata), scripts/autorun.sh, scripts/run.sh
|
|
|
|
## Available Skills
|
|
|
|
EOF
|
|
|
|
# List available skills
|
|
for skill_dir in "$SKILLS_DIR"/*/; do
|
|
local skill_name=$(basename "$skill_dir")
|
|
local skill_md="$skill_dir/SKILL.md"
|
|
|
|
if [ -f "$skill_md" ]; then
|
|
local description=$(yq -r '.description // "No description"' < <(sed -n '/^---$/,/^---$/p' "$skill_md" | sed '1d;$d') 2>/dev/null || echo "No description")
|
|
echo "- **$skill_name**: $description" >> "$prompt_file"
|
|
fi
|
|
done
|
|
|
|
cat >> "$prompt_file" << 'EOF'
|
|
|
|
## Creating/Modifying Skills
|
|
|
|
1. Skills are in /skills/{name}/
|
|
2. Edit files directly
|
|
3. Commit and push changes:
|
|
```bash
|
|
cd /skills/{name}
|
|
git add .
|
|
git commit -m "Description of changes"
|
|
git push
|
|
```
|
|
|
|
## Skill Structure
|
|
|
|
```
|
|
skill-name/
|
|
├── SKILL.md # YAML frontmatter + documentation
|
|
├── scripts/
|
|
│ ├── autorun.sh # Setup/install (runs on skill load)
|
|
│ └── run.sh # Main entry point
|
|
└── config/ # Optional config files
|
|
```
|
|
|
|
## SKILL.md Format
|
|
|
|
```yaml
|
|
---
|
|
name: skill-name
|
|
description: What it does
|
|
metadata:
|
|
version: "1.0.0"
|
|
vibestack:
|
|
main: false
|
|
metrics-port: 8080 # If skill exposes metrics
|
|
requires: # Dependencies
|
|
- other-skill
|
|
---
|
|
|
|
# Skill Name
|
|
|
|
Documentation...
|
|
```
|
|
|
|
## Other Skill APIs
|
|
|
|
- **DuckDB**: POST http://localhost:8432/query {"sql": "..."}
|
|
- **Loki**: GET http://localhost:3100/loki/api/v1/query?query={job="skills"}
|
|
- **Metrics**: GET http://localhost:9090/metrics
|
|
|
|
## Git Configuration
|
|
|
|
Git is configured with token auth. You can push to:
|
|
- https://git.vibe-overflow.com/azat/{skill-name}
|
|
|
|
To create a new skill repo, use the Gitea API or ask the user.
|
|
EOF
|
|
|
|
echo "System prompt generated: $prompt_file"
|
|
}
|
|
|
|
# Configure Caddy if present
|
|
configure_caddy() {
|
|
local caddy_dir="$SKILLS_DIR/caddy"
|
|
local claude_port="${CLAUDE_PORT:-8888}"
|
|
local claude_domain="${CLAUDE_DOMAIN:-}"
|
|
|
|
if [ ! -d "$caddy_dir" ]; then
|
|
echo "Caddy not found - Claude API on port $claude_port"
|
|
return 0
|
|
fi
|
|
|
|
echo "Caddy detected - configuring reverse proxy..."
|
|
mkdir -p "$caddy_dir/snippets.d"
|
|
|
|
local snippet="$caddy_dir/snippets.d/claude.caddy"
|
|
|
|
if [ -n "$claude_domain" ]; then
|
|
cat > "$snippet" << EOF
|
|
# Auto-generated by claude skill
|
|
$claude_domain {
|
|
reverse_proxy localhost:$claude_port
|
|
}
|
|
EOF
|
|
echo "Caddy config: $claude_domain -> localhost:$claude_port"
|
|
else
|
|
cat > "$snippet" << EOF
|
|
# Auto-generated by claude skill
|
|
# Add to your site block:
|
|
# handle /claude/* {
|
|
# uri strip_prefix /claude
|
|
# reverse_proxy localhost:$claude_port
|
|
# }
|
|
EOF
|
|
echo "Caddy snippet created (manual config needed)"
|
|
fi
|
|
}
|
|
|
|
# Validate authentication
|
|
check_auth() {
|
|
if [ -z "$ANTHROPIC_API_KEY" ] && [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then
|
|
echo "WARNING: No authentication configured!"
|
|
echo "Set ANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN"
|
|
else
|
|
echo "Authentication configured"
|
|
fi
|
|
}
|
|
|
|
install_node
|
|
install_claude
|
|
install_deps
|
|
generate_system_prompt
|
|
configure_caddy
|
|
check_auth
|
|
|
|
echo "Claude setup complete"
|