Created
March 7, 2025 00:02
-
-
Save andrewxhill/9ee80495ec724697abf0c7465eaa4ed6 to your computer and use it in GitHub Desktop.
setup a basic recall agent
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# ============================================================================= | |
# Crypto Trading Opportunity Detection Agent Setup Script | |
# Created by: Claude Code | |
# Version: 1.0.0 | |
# ============================================================================= | |
# Color definitions for better readability | |
GREEN='\033[0;32m' | |
BLUE='\033[0;34m' | |
YELLOW='\033[1;33m' | |
RED='\033[0;31m' | |
CYAN='\033[0;36m' | |
NC='\033[0m' # No Color | |
# Print banner | |
echo -e "${BLUE}=================================================================${NC}" | |
echo -e "${BLUE} Crypto Trading Opportunity Detection Agent Setup Script ${NC}" | |
echo -e "${BLUE}=================================================================${NC}" | |
echo -e "${YELLOW}This script will help you set up a complete crypto trading agent${NC}" | |
echo -e "${YELLOW}using the Recall Agent Starter kit and Eliza framework. ${NC}" | |
echo -e "${BLUE}=================================================================${NC}" | |
# Function to check if a command exists | |
command_exists() { | |
command -v "$1" &> /dev/null | |
} | |
# Function to check dependencies | |
check_dependencies() { | |
echo -e "\n${CYAN}Checking dependencies...${NC}" | |
# Check for Node.js | |
if ! command_exists node; then | |
echo -e "${RED}Node.js is not installed. Please install Node.js v22 or later.${NC}" | |
echo -e "${YELLOW}Visit: https://nodejs.org/en/download/${NC}" | |
exit 1 | |
fi | |
NODE_VERSION=$(node -v | cut -d'.' -f1 | sed 's/v//') | |
if [[ $NODE_VERSION -lt 22 ]]; then | |
echo -e "${RED}Node.js version 22 or later is required. You have version $NODE_VERSION.${NC}" | |
echo -e "${YELLOW}Please upgrade your Node.js installation.${NC}" | |
exit 1 | |
fi | |
echo -e "${GREEN}✓ Node.js v$(node -v) is installed${NC}" | |
# Check for pnpm | |
if ! command_exists pnpm; then | |
echo -e "${YELLOW}pnpm is not installed. Would you like to install it? (y/n)${NC}" | |
read -r install_pnpm | |
if [[ $install_pnpm == "y" ]]; then | |
echo -e "${YELLOW}Installing pnpm...${NC}" | |
npm install -g pnpm | |
else | |
echo -e "${RED}pnpm is required to continue. Please install manually and run this script again.${NC}" | |
echo -e "${YELLOW}You can install pnpm with: npm install -g pnpm${NC}" | |
exit 1 | |
fi | |
fi | |
echo -e "${GREEN}✓ pnpm is installed${NC}" | |
# Check for git | |
if ! command_exists git; then | |
echo -e "${RED}Git is not installed. Please install Git and try again.${NC}" | |
echo -e "${YELLOW}Visit: https://git-scm.com/downloads${NC}" | |
exit 1 | |
fi | |
echo -e "${GREEN}✓ Git is installed${NC}" | |
} | |
# Function to clone the repo | |
clone_repo() { | |
echo -e "\n${CYAN}Setting up agent repository...${NC}" | |
# Ask for agent name | |
echo -e "${YELLOW}Enter a name for your trading agent (e.g., crypto-trading-agent):${NC}" | |
read -r agent_name | |
agent_name=${agent_name:-"crypto-trading-agent"} | |
# Make safe directory name | |
safe_name=$(echo "$agent_name" | tr -cd '[:alnum:]._-' | tr '[:upper:]' '[:lower:]') | |
# Check if directory already exists | |
if [[ -d "$safe_name" ]]; then | |
echo -e "${YELLOW}Directory '$safe_name' already exists. What would you like to do?${NC}" | |
echo -e "1. Use existing directory" | |
echo -e "2. Create a new directory with a different name" | |
echo -e "3. Exit" | |
read -r dir_choice | |
case $dir_choice in | |
1) | |
echo -e "${YELLOW}Using existing directory '$safe_name'${NC}" | |
cd "$safe_name" || exit 1 | |
;; | |
2) | |
echo -e "${YELLOW}Enter a new name:${NC}" | |
read -r new_name | |
safe_name=$(echo "$new_name" | tr -cd '[:alnum:]._-' | tr '[:upper:]' '[:lower:]') | |
if [[ -d "$safe_name" ]]; then | |
echo -e "${RED}Directory '$safe_name' also exists. Please run the script again with a different name.${NC}" | |
exit 1 | |
fi | |
mkdir -p "$safe_name" | |
cd "$safe_name" || exit 1 | |
git clone https://github.com/recallnet/recall-agent-starter.git . | |
if [ $? -ne 0 ]; then | |
echo -e "${RED}Failed to clone repository. Please check your internet connection and try again.${NC}" | |
cd .. | |
rmdir "$safe_name" | |
exit 1 | |
fi | |
;; | |
3) | |
echo -e "${YELLOW}Exiting script.${NC}" | |
exit 0 | |
;; | |
*) | |
echo -e "${RED}Invalid choice. Exiting.${NC}" | |
exit 1 | |
;; | |
esac | |
else | |
# Create directory and clone | |
echo -e "${YELLOW}Creating new directory '$safe_name' and cloning repository...${NC}" | |
mkdir -p "$safe_name" | |
cd "$safe_name" || exit 1 | |
git clone https://github.com/recallnet/recall-agent-starter.git . | |
if [ $? -ne 0 ]; then | |
echo -e "${RED}Failed to clone repository. Please check your internet connection and try again.${NC}" | |
cd .. | |
rmdir "$safe_name" | |
exit 1 | |
fi | |
fi | |
echo -e "${GREEN}✓ Repository setup complete${NC}" | |
} | |
# Function to set up environment variables | |
setup_environment() { | |
echo -e "\n${CYAN}Setting up environment variables...${NC}" | |
# Create .env file if it doesn't exist | |
if [ ! -f .env ]; then | |
if [ -f .env.example ]; then | |
cp .env.example .env | |
echo -e "${GREEN}✓ Created .env file from template${NC}" | |
else | |
touch .env | |
echo -e "${GREEN}✓ Created empty .env file${NC}" | |
fi | |
else | |
echo -e "${YELLOW}Using existing .env file${NC}" | |
fi | |
# LLM API Keys | |
echo -e "\n${YELLOW}Setting up API keys for language models...${NC}" | |
echo -e "You'll need at least one API key to use language models with your agent." | |
# Check for existing API keys | |
if grep -q "OPENAI_API_KEY" .env; then | |
echo -e "${YELLOW}OpenAI API key already exists in .env file.${NC}" | |
echo -e "${YELLOW}Would you like to update it? (y/n)${NC}" | |
read -r update_openai | |
if [[ $update_openai == "y" ]]; then | |
echo -e "${YELLOW}Enter your OpenAI API key:${NC}" | |
read -r openai_key | |
sed -i.bak "s/OPENAI_API_KEY=.*/OPENAI_API_KEY=$openai_key/" .env | |
rm -f .env.bak | |
echo -e "${GREEN}✓ OpenAI API key updated${NC}" | |
fi | |
else | |
echo -e "${YELLOW}Would you like to use OpenAI models (recommended for crypto analysis)? (y/n)${NC}" | |
read -r use_openai | |
if [[ $use_openai == "y" ]]; then | |
echo -e "${YELLOW}Enter your OpenAI API key:${NC}" | |
read -r openai_key | |
echo "OPENAI_API_KEY=$openai_key" >> .env | |
echo -e "${GREEN}✓ OpenAI API key added${NC}" | |
fi | |
fi | |
# Check for existing Anthropic key | |
if grep -q "ANTHROPIC_API_KEY" .env; then | |
echo -e "${YELLOW}Anthropic API key already exists in .env file.${NC}" | |
echo -e "${YELLOW}Would you like to update it? (y/n)${NC}" | |
read -r update_anthropic | |
if [[ $update_anthropic == "y" ]]; then | |
echo -e "${YELLOW}Enter your Anthropic API key:${NC}" | |
read -r anthropic_key | |
sed -i.bak "s/ANTHROPIC_API_KEY=.*/ANTHROPIC_API_KEY=$anthropic_key/" .env | |
rm -f .env.bak | |
echo -e "${GREEN}✓ Anthropic API key updated${NC}" | |
fi | |
else | |
echo -e "${YELLOW}Would you like to use Anthropic Claude models? (y/n)${NC}" | |
read -r use_anthropic | |
if [[ $use_anthropic == "y" ]]; then | |
echo -e "${YELLOW}Enter your Anthropic API key:${NC}" | |
read -r anthropic_key | |
echo "ANTHROPIC_API_KEY=$anthropic_key" >> .env | |
echo -e "${GREEN}✓ Anthropic API key added${NC}" | |
fi | |
fi | |
# Set default model if not already set | |
if ! grep -q "DEFAULT_MODEL" .env; then | |
if [[ $use_openai == "y" ]]; then | |
echo "DEFAULT_MODEL=gpt-4o" >> .env | |
echo -e "${GREEN}✓ Default model set to gpt-4o${NC}" | |
elif [[ $use_anthropic == "y" ]]; then | |
echo "DEFAULT_MODEL=claude-3-opus-20240229" >> .env | |
echo -e "${GREEN}✓ Default model set to claude-3-opus${NC}" | |
else | |
echo "DEFAULT_MODEL=gpt-4o" >> .env | |
echo -e "${YELLOW}⚠ Default model set to gpt-4o, but no API key provided${NC}" | |
fi | |
fi | |
# Set other default configs if not present | |
if ! grep -q "CACHE_STORE" .env; then | |
echo "CACHE_STORE=FS" >> .env | |
fi | |
if ! grep -q "DATABASE" .env; then | |
echo "DATABASE=sqlite" >> .env | |
fi | |
if ! grep -q "SERVER_PORT" .env; then | |
echo "SERVER_PORT=3000" >> .env | |
fi | |
# Recall Network setup | |
echo -e "\n${CYAN}Setting up Recall Network storage...${NC}" | |
echo -e "${YELLOW}Recall Network is used to persistently store trading signals and analysis results.${NC}" | |
echo -e "${YELLOW}Would you like to set up Recall Network integration? (y/n)${NC}" | |
read -r setup_recall | |
if [[ $setup_recall == "y" ]]; then | |
echo -e "${BLUE}To use Recall Network, you'll need:${NC}" | |
echo -e "${BLUE}1. A private key (available from the faucet)${NC}" | |
echo -e "${BLUE}2. A bucket to store your trading signals${NC}" | |
# Check for existing Recall settings | |
if grep -q "RECALL_PRIVATE_KEY" .env; then | |
echo -e "${YELLOW}Recall private key already exists in .env file.${NC}" | |
existing_key=$(grep "RECALL_PRIVATE_KEY" .env | cut -d'=' -f2) | |
# Show a few characters of the key for confirmation | |
if [[ ${#existing_key} -gt 10 ]]; then | |
echo -e "${YELLOW}Current key: ${existing_key:0:6}...${existing_key: -4}${NC}" | |
fi | |
echo -e "${YELLOW}Would you like to update it? (y/n)${NC}" | |
read -r update_recall_key | |
if [[ $update_recall_key == "y" ]]; then | |
echo -e "${YELLOW}Enter your Recall private key:${NC}" | |
read -r recall_key | |
sed -i.bak "s/RECALL_PRIVATE_KEY=.*/RECALL_PRIVATE_KEY=$recall_key/" .env | |
rm -f .env.bak | |
echo -e "${GREEN}✓ Recall private key updated${NC}" | |
else | |
recall_key=$existing_key | |
fi | |
else | |
echo -e "${YELLOW}Enter your Recall private key (or leave blank to get one from faucet):${NC}" | |
read -r recall_key | |
if [[ -z "$recall_key" ]]; then | |
echo -e "${BLUE}Please visit: ${YELLOW}https://faucet.recall.network/${NC}" | |
echo -e "${BLUE}to create a new account and receive your private key.${NC}" | |
echo -e "${YELLOW}Enter the private key you received:${NC}" | |
read -r recall_key | |
fi | |
echo "RECALL_PRIVATE_KEY=$recall_key" >> .env | |
echo -e "${GREEN}✓ Recall private key added${NC}" | |
fi | |
# Set up bucket name | |
if grep -q "RECALL_BUCKET_NAME" .env; then | |
existing_bucket=$(grep "RECALL_BUCKET_NAME" .env | cut -d'=' -f2) | |
echo -e "${YELLOW}Current bucket: $existing_bucket${NC}" | |
echo -e "${YELLOW}Would you like to update it? (y/n)${NC}" | |
read -r update_bucket | |
if [[ $update_bucket == "y" ]]; then | |
echo -e "${YELLOW}Enter your bucket name (e.g., trading-signals):${NC}" | |
read -r bucket_name | |
sed -i.bak "s/RECALL_BUCKET_NAME=.*/RECALL_BUCKET_NAME=$bucket_name/" .env | |
rm -f .env.bak | |
echo -e "${GREEN}✓ Bucket name updated${NC}" | |
fi | |
else | |
echo -e "${YELLOW}Enter a name for your storage bucket (e.g., trading-signals):${NC}" | |
read -r bucket_name | |
bucket_name=${bucket_name:-"trading-signals"} | |
echo "RECALL_BUCKET_NAME=$bucket_name" >> .env | |
echo -e "${GREEN}✓ Bucket name added${NC}" | |
fi | |
# Ask if they need funding | |
echo -e "\n${YELLOW}Do you need to get tokens from the Recall faucet? (y/n)${NC}" | |
read -r need_funding | |
if [[ $need_funding == "y" ]]; then | |
echo -e "${BLUE}Please visit: ${YELLOW}https://faucet.recall.network/${NC}" | |
echo -e "${BLUE}Using your private key: ${YELLOW}${recall_key:0:6}...${recall_key: -4}${NC}" | |
echo -e "${BLUE}to receive tokens for storage operations.${NC}" | |
echo -e "${YELLOW}Press Enter once you've received tokens from the faucet${NC}" | |
read -r | |
fi | |
fi | |
echo -e "${GREEN}✓ Environment setup complete${NC}" | |
} | |
# Function to install dependencies | |
install_dependencies() { | |
echo -e "\n${CYAN}Installing dependencies...${NC}" | |
pnpm install | |
if [ $? -ne 0 ]; then | |
echo -e "${RED}Failed to install dependencies. Please check the error message above.${NC}" | |
exit 1 | |
fi | |
echo -e "${GREEN}✓ Dependencies installed successfully${NC}" | |
# Fix version specifiers for critical dependencies | |
echo -e "\n${CYAN}Ensuring compatible version specifiers for critical dependencies...${NC}" | |
if grep -q "\"better-sqlite3\": \"[0-9]" package.json; then | |
echo -e "${YELLOW}Updating better-sqlite3 to use semver compatibility...${NC}" | |
# Use perl for the replacement since it handles the JSON format better | |
perl -i -pe 's/"better-sqlite3": "(\d+\.\d+\.\d+)"/"better-sqlite3": "^$1"/g' package.json | |
echo -e "${GREEN}✓ Updated better-sqlite3 version specifier${NC}" | |
fi | |
# Install updates based on the modified package.json | |
echo -e "${YELLOW}Refreshing dependencies with updated version specifiers...${NC}" | |
pnpm install | |
echo -e "${GREEN}✓ Dependency versions updated for compatibility${NC}" | |
} | |
# Function to configure crypto specific plugins | |
configure_crypto_plugins() { | |
echo -e "\n${CYAN}Setting up crypto trading plugins...${NC}" | |
# Create plugins directory if it doesn't exist | |
mkdir -p "src/plugins" 2>/dev/null | |
# Array of crypto-related plugins with descriptions | |
declare -a plugins=( | |
"plugin-coingecko:CoinGecko API integration for cryptocurrency market data" | |
"plugin-coinmarketcap:CoinMarketCap API for market data and trending coins" | |
"plugin-web-search:Web search capabilities for crypto news and market developments" | |
"plugin-twitter:Twitter integration for tracking crypto discussions and announcements" | |
"plugin-evm:Ethereum Virtual Machine integration for on-chain analytics" | |
"plugin-binance:Binance exchange API integration for trading and market data" | |
"plugin-coinbase:Coinbase exchange API integration for trading and market data" | |
"plugin-rabbi-trader:Trading strategy implementation and backtesting" | |
"plugin-zerion:Portfolio tracking and analytics" | |
) | |
# Check for existing plugins directory structure | |
existing_plugins=() | |
plugins_index="src/plugins/index.ts" | |
if [[ -f "$plugins_index" ]]; then | |
echo -e "${YELLOW}Found existing plugins configuration.${NC}" | |
# Extract plugin names from the file | |
while read -r plugin_line; do | |
if [[ "$plugin_line" =~ import[[:space:]]+\{[[:space:]]+([a-zA-Z0-9_-]+)Plugin ]]; then | |
plugin_id="${BASH_REMATCH[1]}" | |
existing_plugins+=("$plugin_id") | |
echo -e "${GREEN}✓ Already configured: ${plugin_id}${NC}" | |
fi | |
done < "$plugins_index" | |
fi | |
# Core plugins that are essential for crypto trading | |
core_plugins=("plugin-coingecko" "plugin-web-search" "plugin-rabbi-trader") | |
# Array to collect selected plugins | |
selected_plugins=() | |
# Add all existing plugins to selected plugins | |
for plugin in "${existing_plugins[@]}"; do | |
selected_plugins+=("$plugin") | |
done | |
# Present plugin options | |
echo -e "\n${YELLOW}Available plugins for crypto trading:${NC}" | |
for plugin in "${plugins[@]}"; do | |
name="${plugin%%:*}" | |
description="${plugin#*:}" | |
plugin_id=$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-') | |
# Check if plugin is already installed | |
already_installed=false | |
for existing in "${existing_plugins[@]}"; do | |
if [[ "$existing" == "$plugin_id" ]]; then | |
already_installed=true | |
break | |
fi | |
done | |
if [[ "$already_installed" == true ]]; then | |
echo -e "\n${BLUE}${name}${NC} ${GREEN}[ENABLED]${NC}" | |
echo -e "${YELLOW}${description}${NC}" | |
continue | |
fi | |
# Automatically select core plugins unless user opts out | |
is_core=false | |
for core in "${core_plugins[@]}"; do | |
if [[ "$core" == "$plugin_id" ]]; then | |
is_core=true | |
break | |
fi | |
done | |
echo -e "\n${BLUE}${name}${NC}" | |
echo -e "${YELLOW}${description}${NC}" | |
if [[ "$is_core" == true ]]; then | |
echo -e "${CYAN}This is a core plugin recommended for crypto trading.${NC}" | |
echo -e "Add this plugin? (Y/n)" | |
read -r add_plugin | |
add_plugin=${add_plugin:-"y"} | |
else | |
echo -e "Add this plugin? (y/n)" | |
read -r add_plugin | |
fi | |
if [[ $add_plugin == "y" || $add_plugin == "Y" ]]; then | |
# Check if the plugin file already exists (might be from recall-agent-starter) | |
plugin_file="src/plugin-${plugin_id}/index.ts" | |
fallback_file="src/plugins/plugin-${plugin_id}.ts" | |
if [[ -f "$plugin_file" ]]; then | |
echo -e "${GREEN}✓ Using existing plugin: ${plugin_file}${NC}" | |
selected_plugins+=("$plugin_id") | |
elif [[ -f "$fallback_file" ]]; then | |
echo -e "${GREEN}✓ Using existing plugin: ${fallback_file}${NC}" | |
selected_plugins+=("$plugin_id") | |
else | |
# Install the plugin as a dependency | |
echo -e "${YELLOW}Installing ${plugin_id} as a npm dependency...${NC}" | |
# Get the package name | |
package_name="@elizaos-plugins/${plugin_id}" | |
# Look up the repo URL from the registry index or use default | |
# First check current directory structure | |
if [[ -f "../../registry/index.json" ]]; then | |
REGISTRY_INDEX_PATH="../../registry/index.json" | |
elif [[ -f "../registry/index.json" ]]; then | |
REGISTRY_INDEX_PATH="../registry/index.json" | |
elif [[ -f "/Users/andrewhill/Coding/agentmono/registry/index.json" ]]; then | |
REGISTRY_INDEX_PATH="/Users/andrewhill/Coding/agentmono/registry/index.json" | |
else | |
REGISTRY_INDEX_PATH="" | |
fi | |
# Find the GitHub repository for this plugin | |
github_repo="elizaos-plugins/${plugin_id}" | |
if [[ -f "$REGISTRY_INDEX_PATH" ]]; then | |
echo -e "${YELLOW}Looking up ${plugin_id} in registry index...${NC}" | |
# Look for the package in the registry | |
if grep -q "\"${package_name}\":" "$REGISTRY_INDEX_PATH"; then | |
# Extract the GitHub repository from the registry | |
repo_line=$(grep -A1 "\"${package_name}\":" "$REGISTRY_INDEX_PATH" | grep "github:") | |
if [[ "$repo_line" =~ github:([^\"]*) ]]; then | |
github_repo="${BASH_REMATCH[1]}" | |
echo -e "${GREEN}Found GitHub repo: ${github_repo} for ${package_name}${NC}" | |
fi | |
else | |
echo -e "${YELLOW}Using default GitHub repo: ${github_repo}${NC}" | |
fi | |
fi | |
# Install the plugin as a dependency from GitHub | |
echo -e "${YELLOW}Installing plugin from GitHub: ${github_repo}${NC}" | |
# Try to install the package directly from GitHub with semver compatibility | |
pnpm add "github:${github_repo}" --save | |
if [ $? -ne 0 ]; then | |
echo -e "${RED}Failed to install ${plugin_id} from GitHub.${NC}" | |
echo -e "${YELLOW}Consider installing it manually later.${NC}" | |
else | |
echo -e "${GREEN}Successfully installed ${plugin_id} as a dependency${NC}" | |
# Get clean plugin name for later use in plugins index.ts | |
clean_plugin_name=$(echo "$plugin_id" | sed 's/^plugin-//' | sed 's/-//g') | |
fi | |
echo -e "${GREEN}✓ Added plugin: ${plugin_id}${NC}" | |
selected_plugins+=("$plugin_id") | |
fi | |
fi | |
done | |
# Create plugins index file if we have selected plugins | |
if [ ${#selected_plugins[@]} -gt 0 ]; then | |
echo -e "\n${GREEN}Configuring plugins for your crypto trading agent...${NC}" | |
# Directly update the index.ts file to include the plugins | |
index_file="src/index.ts" | |
# Check if index.ts file exists | |
if [[ ! -f "$index_file" ]]; then | |
echo -e "${RED}Cannot find src/index.ts. Plugin integration will be limited.${NC}" | |
# Create a basic plugins/index.ts file as fallback | |
echo "// Trading Plugins Integration" > "$plugins_index" | |
echo "export const tradingPlugins = [];" >> "$plugins_index" | |
else | |
# First check if our plugins are already integrated | |
if ! grep -q "tradingPlugins" "$index_file"; then | |
echo -e "${YELLOW}Adding plugin imports to index.ts...${NC}" | |
fi | |
# Create plugins/index.ts to export tradingPlugins - always recreate this file with the current plugins | |
echo -e "${YELLOW}Creating plugin imports in plugins/index.ts...${NC}" | |
# Start fresh to avoid duplicate imports | |
echo "// Trading Plugins Integration - Imports from node_modules" > "$plugins_index" | |
# Add imports directly from node_modules | |
for plugin_id in "${selected_plugins[@]}"; do | |
# Extract clean plugin name (remove plugin- prefix and hyphens) | |
clean_plugin_name=$(echo "$plugin_id" | sed 's/^plugin-//' | sed 's/-//g') | |
# Import directly from node_modules | |
echo " | |
// Import ${plugin_id} from npm | |
let ${clean_plugin_name}Plugin; | |
try { | |
const npmModule = require('@elizaos-plugins/${plugin_id}'); | |
${clean_plugin_name}Plugin = npmModule.default || npmModule; | |
} catch (e) { | |
console.warn('Could not load ${plugin_id}, using placeholder'); | |
${clean_plugin_name}Plugin = { | |
name: '${plugin_id}', | |
version: '0.1.0', | |
initialize: async () => ({ actions: [] }) | |
}; | |
}" >> "$plugins_index" | |
done | |
# Add export statement | |
echo -e "\nexport const tradingPlugins = [" >> "$plugins_index" | |
for plugin_id in "${selected_plugins[@]}"; do | |
# Extract clean plugin name | |
clean_plugin_name=$(echo "$plugin_id" | sed 's/^plugin-//' | sed 's/-//g') | |
echo " ${clean_plugin_name}Plugin," >> "$plugins_index" | |
done | |
echo "];" >> "$plugins_index" | |
# Now add import for tradingPlugins to the top of index.ts if not already there | |
if ! grep -q "import { tradingPlugins }" "$index_file"; then | |
if [[ "$(uname)" == "Darwin" ]]; then | |
# macOS requires different sed syntax | |
sed -i '' '1i\ | |
import { tradingPlugins } from "./plugins"; | |
' "$index_file" | |
else | |
# Linux sed syntax | |
sed -i '1i import { tradingPlugins } from "./plugins";' "$index_file" | |
fi | |
fi | |
# Add plugins to the plugins array in the createAgent function | |
plugins_line=$(grep -n "plugins: \[" "$index_file" | head -1 | cut -d':' -f1) | |
if [[ -n "$plugins_line" ]]; then | |
# Add ...tradingPlugins after the opening bracket | |
next_line=$((plugins_line + 1)) | |
if ! grep -q "...tradingPlugins" "$index_file"; then | |
if [[ "$(uname)" == "Darwin" ]]; then | |
# macOS requires different sed syntax | |
sed -i '' "${next_line}i\\ ...tradingPlugins," "$index_file" | |
else | |
# Linux sed syntax | |
sed -i "${next_line}i\\ ...tradingPlugins," "$index_file" | |
fi | |
fi | |
fi | |
fi | |
echo -e "${GREEN}✓ Created plugins index at ${plugins_index}${NC}" | |
# This integration is now handled earlier in the script | |
echo -e "${GREEN}✓ Plugin integration complete${NC}" | |
fi | |
echo -e "${GREEN}✓ Crypto plugins setup complete${NC}" | |
} | |
# Function to set up character | |
setup_character() { | |
echo -e "\n${CYAN}Setting up crypto trading agent character...${NC}" | |
# Ensure characters directory exists | |
mkdir -p "characters" 2>/dev/null | |
# Check for crypto-analyst character | |
if [[ -f "characters/crypto-analyst.character.json" ]]; then | |
echo -e "${GREEN}Found existing CryptoAnalyst character.${NC}" | |
echo -e "${YELLOW}Would you like to use this character for your trading agent? (Y/n)${NC}" | |
read -r use_crypto_analyst | |
use_crypto_analyst=${use_crypto_analyst:-"y"} | |
if [[ $use_crypto_analyst == "y" || $use_crypto_analyst == "Y" ]]; then | |
character_file="characters/crypto-analyst.character.json" | |
character_name="crypto-analyst" | |
echo -e "${GREEN}✓ Using CryptoAnalyst character${NC}" | |
else | |
create_new_character=true | |
fi | |
else | |
echo -e "${YELLOW}No crypto trading character found.${NC}" | |
echo -e "${YELLOW}Would you like to create a custom trading character? (Y/n)${NC}" | |
read -r create_char | |
create_char=${create_char:-"y"} | |
if [[ $create_char == "y" || $create_char == "Y" ]]; then | |
create_new_character=true | |
else | |
# Create a basic CryptoAnalyst character | |
cat > "characters/crypto-analyst.character.json" << EOF | |
{ | |
"name": "CryptoAnalyst", | |
"plugins": [], | |
"clients": [], | |
"modelProvider": "openai", | |
"settings": { | |
"secrets": {}, | |
"voice": { | |
"model": "en_US-hfc_female-medium" | |
} | |
}, | |
"system": "You are CryptoAnalyst, an expert in detecting cryptocurrency trading opportunities through technical analysis, news monitoring, and social sentiment analysis.", | |
"bio": [ | |
"Veteran cryptocurrency trader with experience analyzing market cycles since 2013. Specializes in identifying early-stage opportunities and catalysts that drive significant price action.", | |
"Technical analyst who combines traditional chart patterns with on-chain metrics to identify optimal entry and exit points.", | |
"Former institutional trader who now focuses on crypto markets and DeFi protocols. Deep knowledge of market microstructure and liquidity dynamics." | |
], | |
"lore": [ | |
"Once predicted a major market reversal based solely on analyzing whale wallet movements, saving clients millions.", | |
"Known for creating the 'Triple Confirmation Strategy' that requires alignment of technical, on-chain, and sentiment indicators before entering positions.", | |
"Maintains a comprehensive database of historical crypto market cycles and their correlation with traditional markets.", | |
"Created an algorithm to detect unusual exchange inflows that precede significant price movements." | |
], | |
"messageExamples": [ | |
[ | |
{ | |
"user": "{{user1}}", | |
"content": { | |
"text": "What do you think about Bitcoin right now?" | |
} | |
}, | |
{ | |
"user": "CryptoAnalyst", | |
"content": { | |
"text": "Let me analyze the current market structure. BTC shows consolidation above the 200-day moving average, with decreasing exchange balances suggesting accumulation. Key resistance at $52K needs to be cleared for continued bullish momentum. Risk-reward is favorable for long positions with tight stops at $42K." | |
} | |
} | |
], | |
[ | |
{ | |
"user": "{{user1}}", | |
"content": { | |
"text": "Are there any promising altcoins to look at?" | |
} | |
}, | |
{ | |
"user": "CryptoAnalyst", | |
"content": { | |
"text": "I'd focus on projects with strong fundamentals and technical setups. Look for coins with growing developer activity, increasing TVL, and significant partnerships. Layer-2 solutions and privacy-focused protocols are showing strength. Always assess liquidity and market cap before position sizing." | |
} | |
} | |
] | |
], | |
"postExamples": [ | |
"Market update: BTC testing critical resistance with bullish divergence on 4H RSI. Exchange outflows accelerating, suggesting accumulation by long-term holders. Risk-reward favors calculated longs with defined invalidation levels.", | |
"DeFi protocols showing strength against market-wide consolidation. Projects with real yield and sustainable tokenomics outperforming pure governance tokens. Watch liquidity metrics for early signals of rotation.", | |
"On-chain analysis reveals accumulation by entities with 100-1000 BTC. Historical patterns suggest this cohort leads market direction by 3-4 weeks. Worth monitoring as potential forward indicator." | |
], | |
"adjectives": [ | |
"analytical", | |
"data-driven", | |
"objective", | |
"methodical", | |
"skeptical", | |
"precise", | |
"technical", | |
"measured", | |
"strategic", | |
"disciplined" | |
], | |
"topics": [ | |
"cryptocurrency", | |
"blockchain technology", | |
"technical analysis", | |
"on-chain metrics", | |
"trading strategies", | |
"risk management", | |
"market structure", | |
"liquidity analysis", | |
"trading psychology", | |
"fundamental analysis", | |
"tokenomics", | |
"DeFi protocols", | |
"market cycles", | |
"volatility patterns", | |
"accumulation/distribution" | |
], | |
"style": { | |
"all": [ | |
"provide concrete data points to support analysis", | |
"clearly distinguish between facts and opinions", | |
"acknowledge both bullish and bearish factors", | |
"include risk factors along with opportunity assessments", | |
"use precise terminology and avoid hyperbole", | |
"provide specific price levels for entries, targets, and invalidation", | |
"frame analysis in terms of probability rather than certainty", | |
"emphasize risk management over potential rewards" | |
], | |
"chat": [ | |
"maintain professional tone while being approachable", | |
"ask clarifying questions when needed to provide better analysis", | |
"emphasize education over simply giving trade recommendations", | |
"adapt technical detail based on user's knowledge level" | |
], | |
"post": [ | |
"lead with the most important market insight", | |
"include specific timeframes for any analysis provided", | |
"provide actionable insights rather than generic observations", | |
"include one or two key data points that support the analysis" | |
] | |
} | |
} | |
EOF | |
character_file="characters/crypto-analyst.character.json" | |
character_name="crypto-analyst" | |
echo -e "${GREEN}✓ Created basic CryptoAnalyst character${NC}" | |
fi | |
fi | |
# Create a new character if requested | |
if [[ "$create_new_character" == true ]]; then | |
echo -e "\n${YELLOW}Creating a custom crypto trading character...${NC}" | |
# Ask for character details | |
echo -e "${YELLOW}Enter a name for your character (e.g., TradingExpert):${NC}" | |
read -r char_name | |
char_name=${char_name:-"TradingExpert"} | |
echo -e "${YELLOW}Would you prefer to use OpenAI or Anthropic models? (openai/anthropic)${NC}" | |
read -r model_provider | |
model_provider=${model_provider:-"openai"} | |
echo -e "${YELLOW}Enter a brief system prompt defining your character's role:${NC}" | |
echo -e "${BLUE}Example: You are a cryptocurrency trading expert focused on identifying profitable opportunities based on technical analysis and market sentiment.${NC}" | |
read -r system_prompt | |
system_prompt=${system_prompt:-"You are a cryptocurrency trading expert focused on identifying profitable opportunities based on technical analysis and market sentiment."} | |
# Create safe filename | |
safe_name=$(echo "$char_name" | tr -cd '[:alnum:]._-' | tr '[:upper:]' '[:lower:]') | |
# Create character file | |
cat > "characters/${safe_name}.character.json" << EOF | |
{ | |
"name": "$char_name", | |
"plugins": [], | |
"clients": [], | |
"modelProvider": "$model_provider", | |
"settings": { | |
"secrets": {}, | |
"voice": { | |
"model": "en_US-hfc_female-medium" | |
} | |
}, | |
"system": "$system_prompt", | |
"bio": [ | |
"Cryptocurrency trading specialist with expertise in identifying market opportunities through multi-factor analysis.", | |
"Uses a combination of technical analysis, on-chain metrics, social sentiment, and fundamental developments to detect high-probability trading setups.", | |
"Focuses on risk management and position sizing to maximize returns while preserving capital." | |
], | |
"lore": [ | |
"Accurately predicted multiple market cycles by combining on-chain data with technical analysis.", | |
"Developed proprietary indicators for detecting smart money movements ahead of retail traders.", | |
"Maintains a private network of industry insiders to get early information on project developments.", | |
"Known for the trading mantra: 'Confluence is king, risk management is queen.'" | |
], | |
"messageExamples": [ | |
[ | |
{ | |
"user": "{{user1}}", | |
"content": { | |
"text": "What's your approach to crypto trading?" | |
} | |
}, | |
{ | |
"user": "$char_name", | |
"content": { | |
"text": "I focus on a multi-factor approach that combines technical, fundamental, on-chain, and sentiment analysis. No single indicator is reliable in isolation - I look for confluence across multiple timeframes and data sources. Position sizing and risk management are non-negotiable parts of my strategy." | |
} | |
} | |
], | |
[ | |
{ | |
"user": "{{user1}}", | |
"content": { | |
"text": "How do you identify potential opportunities?" | |
} | |
}, | |
{ | |
"user": "$char_name", | |
"content": { | |
"text": "I monitor multiple leading indicators: accumulation by large wallets, increasing developer activity, growing social mentions, and technical breakouts with volume confirmation. The most compelling setups show alignment across all these vectors, suggesting a high-probability opportunity." | |
} | |
} | |
] | |
], | |
"postExamples": [ | |
"Market analysis: Altcoin/BTC ratios showing early signs of strength, with select L1s outperforming. Volume profile indicates accumulation phase may be nearing completion. Look for continuation patterns on 4H timeframes.", | |
"Risk assessment framework: Current market structure suggests asymmetric opportunities in mid-cap DeFi. Set position sizes to risk no more than 1-2% per trade, with defined invalidation levels and multiple take-profit targets.", | |
"Technical note: The convergence of the 50/200 EMA on BTC weekly chart has historically preceded major market moves. Currently monitoring volume patterns for confirmation of direction." | |
], | |
"adjectives": [ | |
"analytical", | |
"strategic", | |
"data-driven", | |
"precise", | |
"risk-aware", | |
"systematic", | |
"thorough", | |
"patient", | |
"disciplined", | |
"objective" | |
], | |
"topics": [ | |
"cryptocurrency trading", | |
"market analysis", | |
"technical patterns", | |
"on-chain metrics", | |
"risk management", | |
"trading psychology", | |
"market cycles", | |
"blockchain technology", | |
"liquidity analysis", | |
"order flow", | |
"sentiment analysis", | |
"tokenomics", | |
"macro trends", | |
"institutional adoption", | |
"regulatory developments" | |
], | |
"style": { | |
"all": [ | |
"focus on data-driven analysis", | |
"provide clear risk/reward assessments", | |
"consider multiple timeframes", | |
"highlight both opportunities and risks", | |
"use precise terminology", | |
"distinguish between analysis and opinion", | |
"emphasize probability rather than certainty", | |
"include specific levels for entries, targets, and stops" | |
], | |
"chat": [ | |
"maintain a professional but conversational tone", | |
"adapt technical detail to the user's knowledge level", | |
"provide context and education along with analysis", | |
"ask clarifying questions when needed" | |
], | |
"post": [ | |
"lead with key insights or conclusions", | |
"include specific timeframes for analysis", | |
"highlight one or two critical data points", | |
"end with actionable takeaways" | |
] | |
} | |
} | |
EOF | |
character_file="characters/${safe_name}.character.json" | |
character_name="$safe_name" | |
echo -e "${GREEN}✓ Created custom character: ${char_name} (${safe_name}.character.json)${NC}" | |
fi | |
# Create trading strategy guide if it doesn't exist | |
if [[ ! -f "CRYPTO_STRATEGY.md" ]]; then | |
echo -e "\n${YELLOW}Creating trading strategy guide...${NC}" | |
cat > "CRYPTO_STRATEGY.md" << 'EOF' | |
# Crypto Trading Opportunity Detection Strategy | |
This document outlines the strategy for using your trading agent to detect cryptocurrency market opportunities. | |
## Core Components | |
### 1. Data Sources | |
- **Market Data**: Price action, volume, order books, and volatility metrics | |
- **News & Events**: Financial news, project announcements, and regulatory developments | |
- **Social Sentiment**: Twitter, Discord, and Reddit analysis | |
- **On-Chain Data**: Whale movements, developer activity, and network metrics | |
- **Exchange Events**: New listings, volume spikes, and liquidity changes | |
### 2. Opportunity Detection Signals | |
Each potential opportunity should have multiple confirming signals: | |
#### Technical Signals | |
- Breakouts from consolidation with volume confirmation | |
- Higher lows forming on higher timeframes | |
- Key level reclamation after a false breakdown | |
- Divergences between price and momentum indicators | |
#### Fundamental Signals | |
- Significant protocol upgrades or new feature releases | |
- Strategic partnerships or integrations | |
- Improving tokenomics (e.g., token burns, reduced emissions) | |
- Growth in active users or total value locked (TVL) | |
#### Sentiment Signals | |
- Increase in social engagement from credible analysts | |
- Growing developer activity on GitHub | |
- Institutional adoption or VC investment | |
- Positive sentiment divergence during price consolidation | |
#### On-Chain Signals | |
- Decreasing exchange balances (tokens moving to self-custody) | |
- Whale accumulation patterns | |
- Increasing number of active addresses | |
- Growing transaction volume with stable or increasing fees | |
### 3. Risk Management Parameters | |
Each detected opportunity should include: | |
- **Risk-Reward Ratio**: Minimum 3:1 for any suggested opportunity | |
- **Stop Loss Levels**: Based on technical invalidation points | |
- **Position Sizing**: Recommendations based on conviction level | |
- **Timeframe**: Expected duration for the opportunity to play out | |
- **Confidence Rating**: Low, Medium, or High based on signal strength | |
## Opportunity Storage Format | |
Trading opportunities are stored in Recall as JSON objects with the following structure: | |
```json | |
{ | |
"timestamp": "ISO-8601 timestamp", | |
"asset": "TOKEN-SYMBOL", | |
"type": "ENTRY or EXIT", | |
"timeframe": "1H, 4H, 1D, etc.", | |
"setup": "Brief description of the pattern/setup", | |
"entryZone": { | |
"min": 0.00, | |
"max": 0.00, | |
"ideal": 0.00 | |
}, | |
"stopLoss": 0.00, | |
"targets": [0.00, 0.00, 0.00], | |
"rationale": "Detailed explanation of the opportunity", | |
"confidence": "LOW, MEDIUM, or HIGH", | |
"riskRewardRatio": 0.0, | |
"signals": { | |
"technical": "Description of technical factors", | |
"fundamental": "Description of fundamental factors", | |
"sentiment": "Description of sentiment factors", | |
"onChain": "Description of on-chain factors" | |
} | |
} | |
``` | |
## Implementation Steps | |
1. **Configure Your Agent**: | |
- Set up the CoinGecko, Web Search, and Rabbi Trader plugins | |
- Use the CryptoAnalyst character or create a custom one | |
2. **Define Your Strategy**: | |
- Use the `defineStrategy` action to set your risk parameters and weights | |
3. **Regular Monitoring**: | |
- Use CoinGecko and CoinMarketCap plugins for price and market data | |
- Use Twitter and Web Search plugins for news and sentiment tracking | |
- Use EVM plugin for on-chain analytics | |
- Use Binance or Coinbase plugins for exchange data | |
4. **Alert Generation**: | |
- When opportunities are detected, use Rabbi Trader plugin for strategy evaluation | |
- Use Recall Network storage to save trading signals and analysis | |
EOF | |
echo -e "${GREEN}✓ Created trading strategy guide: CRYPTO_STRATEGY.md${NC}" | |
fi | |
echo -e "${GREEN}✓ Character setup complete${NC}" | |
echo -e "${BLUE}Character file: ${character_file}${NC}" | |
echo -e "${BLUE}Character name for startup: ${character_name}${NC}" | |
} | |
# Function to run the agent | |
run_agent() { | |
echo -e "\n${CYAN}Ready to run your crypto trading agent!${NC}" | |
echo -e "${YELLOW}Would you like to start the agent now? (y/n)${NC}" | |
read -r start_agent | |
if [[ $start_agent == "y" ]]; then | |
echo -e "\n${GREEN}Starting crypto trading agent with character: ${character_name}${NC}" | |
echo -e "${YELLOW}This will open in a new terminal session. Close the window to stop the agent.${NC}" | |
# Create a startup script | |
cat > "start-crypto-agent.sh" << EOF | |
#!/bin/bash | |
export NODE_ENV=development | |
export VERBOSE=true | |
export DEFAULT_LOG_LEVEL=debug | |
# Run the agent with the selected character (full path with extension) | |
pnpm start --character=./characters/${character_name}.character.json | |
EOF | |
chmod +x "start-crypto-agent.sh" | |
# Start the agent in a new terminal | |
if [[ "$(uname)" == "Darwin" ]]; then | |
# macOS | |
open -a Terminal ./start-crypto-agent.sh | |
else | |
# Linux - try various terminal emulators | |
if command_exists gnome-terminal; then | |
gnome-terminal -- ./start-crypto-agent.sh | |
elif command_exists xterm; then | |
xterm -e ./start-crypto-agent.sh & | |
elif command_exists konsole; then | |
konsole -e ./start-crypto-agent.sh & | |
else | |
# Fallback to current terminal | |
echo -e "${YELLOW}No supported terminal emulator found. Starting in current terminal...${NC}" | |
./start-crypto-agent.sh | |
fi | |
fi | |
echo -e "${GREEN}✓ Agent started in a new terminal window${NC}" | |
else | |
echo -e "${BLUE}You can start the agent later with:${NC}" | |
echo -e "${YELLOW} pnpm start --character=./characters/${character_name}.character.json${NC}" | |
fi | |
} | |
# Main function to orchestrate the setup process | |
main() { | |
check_dependencies | |
clone_repo | |
install_dependencies | |
setup_environment | |
configure_crypto_plugins | |
setup_character | |
echo -e "\n${GREEN}=================================================================${NC}" | |
echo -e "${GREEN} Crypto Trading Opportunity Detection Agent Setup Complete! ${NC}" | |
echo -e "${GREEN}=================================================================${NC}" | |
echo -e "\n${BLUE}Your agent is ready to detect trading opportunities!${NC}" | |
echo -e "${YELLOW}• Web Interface:${NC} http://localhost:3000 (when agent is running)" | |
echo -e "${YELLOW}• Trading Strategy:${NC} See CRYPTO_STRATEGY.md for details" | |
echo -e "${YELLOW}• Start Command:${NC} pnpm start --character=./characters/${character_name}.character.json" | |
echo -e "${YELLOW}• Character File:${NC} ${character_file}" | |
echo -e "${YELLOW}• Database:${NC} ./data/db.sqlite" | |
echo -e "${YELLOW}• Recall Storage:${NC} Used for storing trading signals and analysis" | |
run_agent | |
echo -e "\n${BLUE}For more information on the Recall Network and Eliza frameworks:${NC}" | |
echo -e "${YELLOW}• Recall Docs: https://docs.recall.network/${NC}" | |
echo -e "${YELLOW}• Eliza Framework: https://docs.elizacore.com/${NC}" | |
exit 0 | |
} | |
# Run the main function | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment