From claude-code-tunnels
Installs Claude-Code-Tunnels Project Orchestrator into the project directory, verifies Python 3.10+, registers workspaces, connects messenger channels. Invoke via /claude-code-tunnels:setup-orchestrator.
npx claudepluginhub matteblack9/claude-code-clone --plugin claude-tunnelsThis skill uses the workspace's default tool permissions.
Installs Claude-Code-Tunnels (Project Orchestrator) into the user's project directory.
Runs OrchestKit onboarding wizard: scans codebase for stack detection, configures plugins interactively, generates readiness score and improvement plan. Use for new projects, rescans, or config.
Automates ClaudeClaw setup: installs dependencies, authenticates messaging channels, registers main channel, starts background services. Triggers on setup, install, configure claudeclaw, or first-time requests.
Generates Claude Code project setups including CLAUDE.md, hooks, permissions, commands, and agents. Analyzes stack (TypeScript, JavaScript, Python, Go, Rust, etc.) to create minimal/standard/full configs.
Share bugs, ideas, or general feedback.
Installs Claude-Code-Tunnels (Project Orchestrator) into the user's project directory.
The PO discovers sub-projects/workspaces and delegates tasks via claude-agent-sdk query(cwd=workspace/).
This plugin directory contains the orchestrator code and templates.
PLUGIN_DIR = the directory two levels above this SKILL.md (the plugin root).
Included files: orchestrator/, templates/, orchestrator.yaml, install.sh, requirements.txt
The Orchestrator depends on the Python runtime, pip, and the Claude SDK. Installation paths and versions vary by system, so the current environment must be verified against requirements before installation. If any check fails → do not proceed to the next step until it is resolved.
Why it is needed: the entire orchestrator is written in Python, and claude-agent-sdk requires Python 3.10+.
Auto-detect available Python installations on the system:
candidates=()
for cmd in python3 python python3.12 python3.11 python3.10; do
full=$(command -v "$cmd" 2>/dev/null) || continue
ver=$("$full" -c "import sys; v=sys.version_info; print(f'{v.major}.{v.minor}')" 2>/dev/null) || continue
major=${ver%%.*}; minor=${ver#*.}
if [ "$major" -ge 3 ] && [ "$minor" -ge 10 ]; then
candidates+=("$full ($cmd $ver)")
fi
done
Present the detected results as numbered choices:
Select a Python 3.10+ runtime.
The Orchestrator code and claude-agent-sdk will run using this Python.
[1] /usr/bin/python3 (python3 3.11.5) <- detected
[2] /usr/local/bin/python3.12 (python3.12 3.12.1) <- detected
[3] Enter manually
Number or path:
1 or 2 → set that path as PYTHON_CMD3 or a direct path → verify that path's version and use itWhy it is needed: used to install and verify Python packages such as claude-agent-sdk, aiohttp, and pyyaml.
pip_candidates=()
for cmd in "$PYTHON_CMD -m pip" pip3 pip; do
if $cmd --version &>/dev/null 2>&1; then
pip_candidates+=("$cmd")
fi
done
Select pip. It will be used to install dependency packages.
[1] /usr/bin/python3 -m pip (pip 23.2.1) <- detected
[2] Enter manually
Number or path:
Why it is needed: claude-agent-sdk internally calls the claude CLI binary. Without it, query() calls will fail.
claude_path=$(command -v claude 2>/dev/null)
$claude_path (claude --version). OK?"Claude CLI not found.
The claude-agent-sdk query() internally calls the claude binary, so it is required.
[1] Enter path manually (e.g. ~/.npm/bin/claude)
[2] Install now (npm install -g @anthropic-ai/claude-code)
[3] Install later (continue without installing — errors may occur at runtime)
Number:
Why they are needed: each package serves a distinct role.
claude-agent-sdk: the core library for invoking Claude Code programmatically from Pythonaiohttp: used by channel adapters (Telegram polling) and the remote listener to handle async HTTPpyyaml: parses the orchestrator.yaml configuration filedeclare -A pkg_status
for pkg in claude_agent_sdk aiohttp yaml; do
if $PYTHON_CMD -c "import $pkg" 2>/dev/null; then
pkg_status[$pkg]="OK"
else
pkg_status[$pkg]="NOT INSTALLED"
fi
done
If any packages are missing:
The following packages are not installed:
- claude-agent-sdk (Claude SDK — orchestrator cannot run without it)
- aiohttp (async HTTP — channel/remote connections will fail without it)
Install command: $PIP_CMD install claude-agent-sdk aiohttp pyyaml
[1] Install now
[2] Skip (install manually later)
Number:
Environment Preflight Results
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Python: /usr/bin/python3 (3.11.5) ✓
pip: /usr/bin/python3 -m pip (23.2.1) ✓
Claude CLI: /usr/local/bin/claude (1.0.35) ✓
claude-agent-sdk: 0.3.0 ✓
aiohttp: 3.9.1 ✓
pyyaml: 6.0.1 ✓
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All checks passed. Proceed with setup? (yes/no)
Now that the environment check is complete, determine the installation location and channels. Auto-detect possible values and present them as numbered choices. The user only needs to enter a number.
Present the current directory and its parent as candidates:
cwd=$(pwd)
parent=$(dirname "$cwd")
# Treat paths with 2 or more subdirectories as project root candidates
candidates=()
for d in "$cwd" "$parent"; do
subdir_count=$(find "$d" -maxdepth 1 -mindepth 1 -type d ! -name '.*' | wc -l)
if [ "$subdir_count" -ge 1 ]; then
candidates+=("$d (${subdir_count} subdirectories)")
fi
done
Select the project root directory.
Sub-projects/workspaces must reside inside this directory.
[1] /home/user/my-projects (4 subdirectories) <- current location
[2] /home/user (7 subdirectories) <- parent
[3] Enter manually
Number or absolute path:
Validation: test -d && test -w
Select the credential storage path.
Slack/Telegram tokens and similar secrets will be stored here. (excluded from git)
[1] $PROJECT_ROOT/ARCHIVE <- recommended default
[2] Enter manually
Number or absolute path:
Select the messenger channels to connect.
The Orchestrator will receive messages from these channels and execute tasks.
Multiple selections allowed — separate numbers with commas (e.g. 1,3)
[1] slack — Slack Socket Mode (no public IP required)
[2] telegram — Telegram Bot long polling (no public IP required)
[3] Configure later (skip)
Number:
test -d "$PROJECT_ROOT" || echo "ERROR: $PROJECT_ROOT does not exist."
test -w "$PROJECT_ROOT" || echo "ERROR: $PROJECT_ROOT is not writable."
mkdir -p "$ARCHIVE_PATH" 2>/dev/null || echo "ERROR: Failed to create $ARCHIVE_PATH."
If validation fails → re-present choices for that item only. Do not automatically substitute a value.
Show the list of files to be copied and confirm with the user:
PLUGIN_DIR="<plugin root path>"
echo "The following files will be copied to $PROJECT_ROOT:"
echo " orchestrator/ <- Python package (PO, executor, router, channels)"
echo " .claude/rules/ <- delegation, task-log, notification rules"
echo " start-orchestrator.sh <- startup script (uses $PYTHON_CMD)"
echo "Proceed? (yes/no)"
# After user confirmation:
cp -r $PLUGIN_DIR/orchestrator/ $PROJECT_ROOT/orchestrator/
mkdir -p $PROJECT_ROOT/.claude/rules/
cp $PLUGIN_DIR/templates/rules/*.md $PROJECT_ROOT/.claude/rules/
# start-orchestrator.sh — apply PYTHON_CMD
sed "s|python3|$PYTHON_CMD|g" $PLUGIN_DIR/templates/start-orchestrator.sh.template \
> $PROJECT_ROOT/start-orchestrator.sh
chmod +x $PROJECT_ROOT/start-orchestrator.sh
Generate using the collected user inputs, then display the content and confirm:
root: $PROJECT_ROOT
archive: $ARCHIVE_PATH
channels:
slack:
enabled: true/false
telegram:
enabled: true/false
remote_workspaces: []
$PLUGIN_DIR/templates/CLAUDE.md.templateAuto-detect subdirectories and present as a checklist:
ls $PROJECT_ROOT/ # exclude: orchestrator/, ARCHIVE/, .tasks/, .claude/, .git/, hidden folders
The following subdirectories were found.
Select the ones to register as workspaces (separate numbers with commas, or enter all):
[1] project-a/ (CLAUDE.md present)
[2] project-b/ (CLAUDE.md present)
[3] project-c/ (no CLAUDE.md — a default will be generated)
[4] data-scripts/ (no CLAUDE.md — a default will be generated)
Number (e.g. 1,2,3 or all):
Workspaces without a CLAUDE.md will be informed that a default one will be created.
Run the corresponding channel skill in sequence based on the selected channels:
/claude-code-tunnels:connect-slack/claude-code-tunnels:connect-telegramDependency installation (show list to user and confirm):
Packages to install:
Base: claude-agent-sdk aiohttp pyyaml
Slack: slack-bolt slack-sdk
Command: $PIP_CMD install claude-agent-sdk aiohttp pyyaml slack-bolt slack-sdk
[1] Install now
[2] Skip (install manually)
Number:
cd $PROJECT_ROOT && ./start-orchestrator.sh --fg &
sleep 3
# Slack: confirm "Socket Mode" in logs
# Telegram: confirm bot username in logs
If the test fails → explain the situation to the user with the error message. Do not retry automatically.
Final summary:
Setup Complete!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Project Root: /home/user/my-projects
Archive: /home/user/my-projects/ARCHIVE
Python: /usr/bin/python3 (3.11.5)
Channels: slack ✓, telegram ✗
Workspaces: project-a, project-b, project-c
Files created:
orchestrator/ <- Python package
orchestrator.yaml <- configuration file
start-orchestrator.sh <- startup script
.claude/rules/ <- delegation rules
CLAUDE.md <- PO description
Next steps:
./start-orchestrator.sh <- start in background
./start-orchestrator.sh --fg <- foreground (debug)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
All credential files share the same format:
key : value
Spaces are required on both sides of the colon. Even if bot_token contains a colon, only the first : is used as the split point.
PROJECT_ROOT/
├── orchestrator/ <- PO, executor, router, channels
│ ├── __init__.py
│ ├── main.py
│ ├── server.py
│ ├── po.py
│ ├── executor.py
│ ├── router.py
│ ├── channel/ <- Slack, Telegram adapters
│ └── remote/ <- listener, deploy helpers
├── orchestrator.yaml <- configuration file
├── start-orchestrator.sh <- startup script
├── CLAUDE.md <- project description for the PO
├── .claude/rules/ <- delegation, task-log, notification rules
├── ARCHIVE/ <- credentials (excluded from git)
├── .tasks/ <- task history logs
├── project-a/ <- workspace
│ └── CLAUDE.md
└── project-b/ <- workspace
└── CLAUDE.md