fix: install skill as self-contained bundle, harden installer

- Install entire skill dir (SKILL.md + scripts/ + references/) into
  ~/.openclaw/skills/ (shared skill location per OpenClaw docs)
- Scripts live inside the skill folder, not a separate global dir
- Node.js 22 check is now a hard error, not a warning
- timeout check is a hard error (required for delegate.sh)
- Add --force flag to reinstall npm packages on rerun
- Pin npm packages to @latest explicitly
- Drop darwin from os metadata (requires GNU coreutils)
- Fix set -e killing exit code capture in delegate.sh
This commit is contained in:
Robert Koller 2026-03-16 05:18:40 +00:00
parent caf8a05e04
commit 6fbffd98fa
3 changed files with 103 additions and 73 deletions

View File

@ -2,7 +2,7 @@
name: claude-codex-delegation
description: Delegate code-writing, document generation, and analysis tasks to Claude Code or OpenAI Codex sub-processes. Use when you need to spawn a coding agent for file generation, code modification, script writing, or any multi-step coding task. Triggers on "delegate to claude", "delegate to codex", "use claude code", "use codex", "spawn coding agent", "run delegation", or when a task requires writing/modifying code that should be handed off to a sub-process.
metadata:
{ "openclaw": { "os": ["linux", "darwin"], "requires": { "anyBins": ["claude", "codex"], "bins": ["bash", "timeout"] } } }
{ "openclaw": { "os": ["linux"], "requires": { "anyBins": ["claude", "codex"], "bins": ["bash", "timeout"] } } }
---
# Claude Code + Codex Delegation

View File

@ -1,33 +1,38 @@
#!/usr/bin/env bash
# install.sh Install Claude Code + Codex delegation bundle for OpenClaw.
# install.sh - Install Claude Code + Codex delegation bundle for OpenClaw.
#
# Installs the Claude Code and Codex CLIs, copies delegation scripts
# into your OpenClaw workspace, and verifies the setup.
# Copies the entire skill directory (SKILL.md, scripts, references) into
# OpenClaw's shared skill location so the agent can discover and use it.
# Optionally installs the Claude Code and Codex CLIs via npm.
#
# Usage:
# install.sh [options]
#
# Options:
# --skip-npm Skip npm package installation (if already installed)
# --scripts-dir DIR Where to install scripts (default: ~/.openclaw/scripts)
# --skill-dir DIR Override skill install location
# (default: ~/.openclaw/skills/claude-codex-delegation)
# --force Reinstall npm packages even if already present
# --dry-run Show what would be done without doing it
# -h, --help Show this help message
#
# Requirements:
# - Node.js 22+ with npm
# - Existing OpenClaw installation
# - GNU coreutils (timeout, script) on Linux; macOS needs coreutils via brew
# - Claude Max or OpenAI subscription (for subscription-based auth)
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPTS_DIR="${HOME}/.openclaw/scripts"
SKILL_DIR="${HOME}/.openclaw/skills/claude-codex-delegation"
SKIP_NPM=false
FORCE=false
DRY_RUN=false
# --- Versions (pin to known-good releases) ---
CLAUDE_CODE_PKG="@anthropic-ai/claude-code"
CODEX_PKG="@openai/codex"
# --- Pinned versions ---
CLAUDE_CODE_PKG="@anthropic-ai/claude-code@latest"
CODEX_PKG="@openai/codex@latest"
# --- Colors ---
RED='\033[0;31m'
@ -42,16 +47,14 @@ error() { echo -e "${RED}[ERROR]${NC} $*" >&2; }
# --- Parse arguments ---
while [[ $# -gt 0 ]]; do
case "$1" in
--skip-npm|--scripts-dir|--dry-run)
if [[ "$1" == "--scripts-dir" ]]; then
if [[ $# -lt 2 ]]; then
echo "Error: $1 requires a value" >&2
exit 1
fi
--skill-dir)
if [[ $# -lt 2 ]]; then
echo "Error: $1 requires a value" >&2
exit 1
fi
;;&
SKILL_DIR="$2"; shift 2 ;;
--skip-npm) SKIP_NPM=true; shift ;;
--scripts-dir) SCRIPTS_DIR="$2"; shift 2 ;;
--force) FORCE=true; shift ;;
--dry-run) DRY_RUN=true; shift ;;
-h|--help)
sed -n '2,/^$/p' "$0" | sed 's/^# \?//'
@ -70,7 +73,7 @@ run() {
}
echo ""
echo "Claude Code + Codex Delegation Installer"
echo "Claude Code + Codex Delegation - Installer"
echo "============================================"
echo ""
@ -83,8 +86,11 @@ fi
NODE_MAJOR="$(node -v | sed 's/^v//' | cut -d. -f1)"
if [[ "$NODE_MAJOR" -lt 22 ]]; then
warn "Node.js $(node -v) detected. Version 22+ is recommended."
error "Node.js $(node -v) detected. Version 22+ is required."
echo " Install Node.js 22+: curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -"
exit 1
fi
info "Node.js $(node -v)"
if ! command -v npm &> /dev/null; then
error "npm is not installed."
@ -98,12 +104,38 @@ if ! command -v openclaw &> /dev/null; then
fi
info "OpenClaw detected ($(openclaw --version 2>/dev/null || echo 'unknown version'))"
# --- Install Claude Code ---
# --- Check required system utilities ---
echo ""
echo "Checking system dependencies..."
MISSING=0
if ! command -v timeout &> /dev/null; then
error "'timeout' is required but not found."
if [[ "$(uname)" == "Darwin" ]]; then
echo " Install with: brew install coreutils"
fi
((MISSING++))
else
info "timeout: available"
fi
if command -v tmux &> /dev/null; then
info "tmux: available"
else
warn "tmux: not installed (optional, needed for tmux-session.sh)"
fi
if [[ $MISSING -gt 0 ]]; then
error "Missing $MISSING required system dependency. Install it and rerun."
exit 1
fi
# --- Install Claude Code and Codex ---
if ! $SKIP_NPM; then
echo ""
echo "Installing Claude Code..."
if command -v claude &> /dev/null; then
info "Claude Code already installed ($(claude --version 2>/dev/null || echo 'unknown version'))"
if command -v claude &> /dev/null && ! $FORCE; then
info "Claude Code already installed ($(claude --version 2>/dev/null || echo 'unknown version')). Use --force to reinstall."
else
run npm install -g "$CLAUDE_CODE_PKG"
if ! $DRY_RUN; then
@ -113,8 +145,8 @@ if ! $SKIP_NPM; then
echo ""
echo "Installing OpenAI Codex CLI..."
if command -v codex &> /dev/null; then
info "Codex CLI already installed ($(codex --version 2>/dev/null || echo 'unknown version'))"
if command -v codex &> /dev/null && ! $FORCE; then
info "Codex CLI already installed ($(codex --version 2>/dev/null || echo 'unknown version')). Use --force to reinstall."
else
run npm install -g "$CODEX_PKG"
if ! $DRY_RUN; then
@ -123,35 +155,38 @@ if ! $SKIP_NPM; then
fi
fi
# --- Install delegation scripts ---
# --- Install skill bundle ---
# Copies the entire skill directory (SKILL.md, scripts/, references/) into
# OpenClaw's shared skill location (~/.openclaw/skills/) so the agent
# discovers it automatically. All resources stay inside the skill folder.
echo ""
echo "Installing delegation scripts to $SCRIPTS_DIR..."
run mkdir -p "$SCRIPTS_DIR"
for script in delegate.sh tmux-session.sh; do
SRC="$SCRIPT_DIR/scripts/$script"
DST="$SCRIPTS_DIR/$script"
if [[ -f "$SRC" ]]; then
run cp "$SRC" "$DST"
run chmod +x "$DST"
info "Installed $script"
else
warn "Script not found: $SRC"
fi
done
# --- Install skill file ---
echo ""
echo "Installing skill definition..."
SKILL_DIR="${HOME}/.openclaw/workspace/skills/claude-codex-delegation"
echo "Installing skill bundle to $SKILL_DIR..."
run mkdir -p "$SKILL_DIR/scripts"
run mkdir -p "$SKILL_DIR/references"
# SKILL.md
if [[ -f "$SCRIPT_DIR/SKILL.md" ]]; then
run cp "$SCRIPT_DIR/SKILL.md" "$SKILL_DIR/SKILL.md"
info "Installed SKILL.md"
fi
# Scripts (inside the skill directory, not a global scripts dir)
for script in delegate.sh tmux-session.sh; do
SRC="$SCRIPT_DIR/scripts/$script"
DST="$SKILL_DIR/scripts/$script"
if [[ -f "$SRC" ]]; then
run cp "$SRC" "$DST"
run chmod +x "$DST"
info "Installed scripts/$script"
else
error "Script not found: $SRC"
fi
done
# References
if [[ -f "$SCRIPT_DIR/references/delegation-policy.md" ]]; then
run cp "$SCRIPT_DIR/references/delegation-policy.md" "$SKILL_DIR/references/delegation-policy.md"
info "Installed delegation-policy.md"
info "Installed references/delegation-policy.md"
fi
# --- Verify ---
@ -173,43 +208,36 @@ else
((ERRORS++))
fi
if [[ -x "$SCRIPTS_DIR/delegate.sh" ]] || $DRY_RUN; then
info "delegate.sh: OK"
if [[ -f "$SKILL_DIR/SKILL.md" ]] || $DRY_RUN; then
info "SKILL.md: OK"
else
error "delegate.sh: not found or not executable"
error "SKILL.md: not found at $SKILL_DIR"
((ERRORS++))
fi
if [[ -x "$SCRIPTS_DIR/tmux-session.sh" ]] || $DRY_RUN; then
info "tmux-session.sh: OK"
if [[ -x "$SKILL_DIR/scripts/delegate.sh" ]] || $DRY_RUN; then
info "scripts/delegate.sh: OK"
else
error "tmux-session.sh: not found or not executable"
error "scripts/delegate.sh: not found or not executable"
((ERRORS++))
fi
# --- Optional dependencies ---
echo ""
if command -v tmux &> /dev/null; then
info "tmux: available (for long-running sessions)"
if [[ -x "$SKILL_DIR/scripts/tmux-session.sh" ]] || $DRY_RUN; then
info "scripts/tmux-session.sh: OK"
else
warn "tmux: not installed (optional — needed for tmux-session.sh)"
fi
if command -v timeout &> /dev/null; then
info "timeout: available"
else
warn "timeout: not found (needed for delegate.sh)"
error "scripts/tmux-session.sh: not found or not executable"
((ERRORS++))
fi
# --- Auth check ---
echo ""
echo "Checking auth..."
echo " Claude Code auth: run 'claude auth' to verify subscription/OAuth is configured"
echo " Codex auth: run 'codex auth' to verify OpenAI subscription is configured"
echo " Claude Code: run 'claude auth' to verify subscription/OAuth is configured"
echo " Codex: run 'codex auth' to verify OpenAI subscription is configured"
echo ""
echo " NOTE: The delegation scripts strip API keys from the sub-process"
echo " environment. Both Claude Code and Codex must be configured with"
echo " subscription/OAuth auth — API key auth will NOT work."
echo " environment. Both CLIs must be configured with subscription/OAuth"
echo " auth. API key auth will NOT work."
# --- Summary ---
echo ""
@ -217,13 +245,15 @@ if [[ $ERRORS -eq 0 ]]; then
echo "============================================"
info "Installation complete."
echo ""
echo " Skill installed to: $SKILL_DIR"
echo ""
echo " Delegate a task:"
echo " $SCRIPTS_DIR/delegate.sh --prompt 'Your task' --workdir ~/project"
echo " $SKILL_DIR/scripts/delegate.sh --prompt 'Your task' --workdir ~/project"
echo ""
echo " Long-running task in tmux:"
echo " $SCRIPTS_DIR/tmux-session.sh --name my-task --prompt 'Your task' --workdir ~/project"
echo " $SKILL_DIR/scripts/tmux-session.sh --name my-task --prompt 'Your task' --workdir ~/project"
echo ""
echo " See SKILL.md for full usage and security documentation."
echo " OpenClaw will discover the skill automatically on next session."
echo "============================================"
else
error "$ERRORS verification error(s). Check the output above."

View File

@ -185,11 +185,11 @@ ESCAPED_LOG="$(printf '%q' "$LOG_FILE")"
if $BACKGROUND; then
(
EXIT_CODE=0
timeout "$TIMEOUT" bash -c "$(declare -f run_delegation build_claude_cmd build_codex_cmd); \
AGENT='$AGENT' PROMPT='$(printf '%s' "$PROMPT" | sed "s/'/'\\\\''/g")' \
WORKDIR=$ESCAPED_WORKDIR LOG_FILE=$ESCAPED_LOG FULL_AUTO=$FULL_AUTO \
run_delegation"
EXIT_CODE=$?
run_delegation" || EXIT_CODE=$?
echo ""
echo "--- Delegation complete (exit code: $EXIT_CODE) ---"
) >> "$LOG_FILE" 2>&1 &
@ -197,11 +197,11 @@ if $BACKGROUND; then
echo "Background PID: $BG_PID"
echo "Monitor: tail -f $LOG_FILE"
else
EXIT_CODE=0
timeout "$TIMEOUT" bash -c "$(declare -f run_delegation build_claude_cmd build_codex_cmd); \
AGENT='$AGENT' PROMPT='$(printf '%s' "$PROMPT" | sed "s/'/'\\\\''/g")' \
WORKDIR=$ESCAPED_WORKDIR LOG_FILE=$ESCAPED_LOG FULL_AUTO=$FULL_AUTO \
run_delegation"
EXIT_CODE=$?
run_delegation" || EXIT_CODE=$?
if [[ $EXIT_CODE -eq 0 ]]; then
echo "Delegation complete."
elif [[ $EXIT_CODE -eq 124 ]]; then