Files
seobuild-onpage/scripts/setup.py
T
Greg BessoniandClaude Opus 4.6 ae47fcccba seo-agi: The GEO framework skill for Claude Code + OpenClaw
GEO framework that writes pages ranking on Google AND getting cited by
LLMs. 500-token chunk architecture, Reddit Test quality gates,
verification tags, Not For You blocks, information gain enforcement.

Data layer: DataForSEO, GSC, Ahrefs MCP, SEMRush MCP.
21 files, all tests passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-18 10:56:28 -04:00

161 lines
5.3 KiB
Python

#!/usr/bin/env python3
"""
SEO-AGI setup script.
Creates config directory, prompts for API keys, installs dependencies.
Usage:
python3 setup.py
"""
import os
import sys
import json
import subprocess
from pathlib import Path
CONFIG_DIR = Path.home() / ".config" / "seo-agi"
ENV_FILE = CONFIG_DIR / ".env"
CONFIG_FILE = CONFIG_DIR / "config.json"
OUTPUT_DIR = Path.home() / "Documents" / "SEO-AGI"
def main():
print("=" * 50)
print(" SEO-AGI Setup")
print("=" * 50)
print()
# Create directories
CONFIG_DIR.mkdir(parents=True, exist_ok=True)
for subdir in ["research", "briefs", "pages", "rewrites"]:
(OUTPUT_DIR / subdir).mkdir(parents=True, exist_ok=True)
data_dir = Path.home() / ".local" / "share" / "seo-agi"
for subdir in ["research", "cache"]:
(data_dir / subdir).mkdir(parents=True, exist_ok=True)
print("[OK] Directories created")
# Install Python dependencies
print("\nInstalling dependencies...")
deps = ["requests"]
try:
subprocess.check_call(
[sys.executable, "-m", "pip", "install", "--quiet"]
+ deps
+ ["--break-system-packages"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
print("[OK] Core dependencies installed (requests)")
except subprocess.CalledProcessError:
try:
subprocess.check_call(
[sys.executable, "-m", "pip", "install", "--quiet"] + deps,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
print("[OK] Core dependencies installed (requests)")
except subprocess.CalledProcessError:
print("[WARN] Could not install requests. Install manually:")
print(" pip install requests")
# API Keys
print("\n--- API Keys ---")
print("DataForSEO is REQUIRED. Get credentials at:")
print(" https://app.dataforseo.com/api-dashboard\n")
existing_env = {}
if ENV_FILE.exists():
with open(ENV_FILE) as f:
for line in f:
line = line.strip()
if line and not line.startswith("#") and "=" in line:
k, _, v = line.partition("=")
existing_env[k.strip()] = v.strip()
# DataForSEO
dfs_login = existing_env.get("DATAFORSEO_LOGIN", "")
dfs_pass = existing_env.get("DATAFORSEO_PASSWORD", "")
if dfs_login:
print(f"DataForSEO login found: {dfs_login[:4]}***")
change = input("Update DataForSEO credentials? [y/N]: ").strip().lower()
if change == "y":
dfs_login = input("DataForSEO login (email): ").strip()
dfs_pass = input("DataForSEO password: ").strip()
else:
dfs_login = input("DataForSEO login (email): ").strip()
dfs_pass = input("DataForSEO password: ").strip()
# GSC (optional)
print("\nGoogle Search Console (OPTIONAL - press Enter to skip)")
gsc_path = existing_env.get("GSC_SERVICE_ACCOUNT_PATH", "")
if gsc_path:
print(f"GSC service account found: {gsc_path}")
change = input("Update? [y/N]: ").strip().lower()
if change == "y":
gsc_path = input("Path to service account JSON: ").strip()
else:
gsc_path = input("Path to GSC service account JSON (or Enter to skip): ").strip()
# Write .env
env_lines = [
"# SEO-AGI Configuration",
f"# Generated by setup.py on {__import__('datetime').datetime.now().isoformat()[:10]}",
"",
"# DataForSEO",
f"DATAFORSEO_LOGIN={dfs_login}",
f"DATAFORSEO_PASSWORD={dfs_pass}",
"",
"# Google Search Console",
f"GSC_SERVICE_ACCOUNT_PATH={gsc_path}",
"",
"# Future integrations",
f"AHREFS_API_KEY={existing_env.get('AHREFS_API_KEY', '')}",
f"SEMRUSH_API_KEY={existing_env.get('SEMRUSH_API_KEY', '')}",
"",
"# Defaults",
f"DEFAULT_LOCATION={existing_env.get('DEFAULT_LOCATION', '2840')}",
f"DEFAULT_LANGUAGE={existing_env.get('DEFAULT_LANGUAGE', 'en')}",
]
with open(ENV_FILE, "w") as f:
f.write("\n".join(env_lines) + "\n")
print(f"\n[OK] Credentials saved to {ENV_FILE}")
# Write default config.json if not exists
if not CONFIG_FILE.exists():
default_config = {
"default_location": 2840,
"default_language": "en",
"default_site": "",
"serp_depth": 10,
"save_research": True,
"output_dir": str(OUTPUT_DIR),
}
with open(CONFIG_FILE, "w") as f:
json.dump(default_config, f, indent=2)
print(f"[OK] Config saved to {CONFIG_FILE}")
# Verify
print("\n--- Setup Summary ---")
print(f" DataForSEO: {'configured' if dfs_login else 'NOT SET'}")
print(f" GSC: {'configured' if gsc_path else 'not configured (optional)'}")
print(f" Output dir: {OUTPUT_DIR}")
print(f" Config dir: {CONFIG_DIR}")
if dfs_login:
print("\n[READY] Run a test:")
print(f" python3 {Path(__file__).parent}/research.py \"test keyword\"")
else:
print("\n[WARN] DataForSEO credentials missing. The skill will fall")
print(" back to Claude's web search for basic research.")
print()
if __name__ == "__main__":
main()