From 60d1f8fd06bf72dae6cf68d83fb40fbaba6f86f0 Mon Sep 17 00:00:00 2001 From: Yassine Bargach Date: Sun, 8 Feb 2026 13:22:48 +0100 Subject: [PATCH 1/3] playwright issue --- .github/workflows/build-release.yml | 10 +- deadend_cli/installer/deadend.sh | 4 + deadend_cli/installer/fix_permissions.sh | 9 + .../installer/install_playwright_browsers.sh | 123 +++++++++---- install.sh | 173 ++++++++++++++---- 5 files changed, 243 insertions(+), 76 deletions(-) mode change 100644 => 100755 install.sh diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index d8f1b69a..95ecb68e 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -88,7 +88,15 @@ jobs: BROWSER_PATH="${{ steps.build_dir.outputs.build_dir }}/lib/playwright/driver/package/.local-browsers" echo "Checking browser installation at: $BROWSER_PATH" ls -la "$BROWSER_PATH" || echo "Browser directory not found" - find "$BROWSER_PATH" -type f -name "chrome*" -o -name "chromium*" | head -5 || echo "No browser binaries found" + echo "" + echo "Looking for chromium_headless_shell directories:" + find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium_headless_shell-*" || echo "No chromium_headless_shell directories found" + echo "" + echo "Looking for browser executables:" + find "$BROWSER_PATH" -type f \( -name "chrome-headless-shell" -o -name "chrome-headless-shell*" -o -name "chrome*" -o -name "chromium*" \) | head -10 || echo "No browser binaries found" + echo "" + echo "Checking directory structure:" + find "$BROWSER_PATH" -type d -name "*chrome*" -o -name "*chromium*" | head -10 || echo "No browser directories found" - name: Create package directory structure id: package diff --git a/deadend_cli/installer/deadend.sh b/deadend_cli/installer/deadend.sh index 694f8ec9..d2e3d42d 100755 --- a/deadend_cli/installer/deadend.sh +++ b/deadend_cli/installer/deadend.sh @@ -5,6 +5,10 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Include both lib and numpy/libs directories for OpenBLAS and other shared libraries export LD_LIBRARY_PATH="${SCRIPT_DIR}/lib:${SCRIPT_DIR}/lib/numpy/libs${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" +# Set PLAYWRIGHT_BROWSERS_PATH so Playwright knows where to find browsers +# This must point to the .local-browsers directory +export PLAYWRIGHT_BROWSERS_PATH="${SCRIPT_DIR}/lib/playwright/driver/package/.local-browsers" + # Ensure Playwright driver has execute permissions if [ -f "${SCRIPT_DIR}/lib/playwright/driver/node" ]; then chmod +x "${SCRIPT_DIR}/lib/playwright/driver/node" 2>/dev/null diff --git a/deadend_cli/installer/fix_permissions.sh b/deadend_cli/installer/fix_permissions.sh index 0b311d28..04352c20 100755 --- a/deadend_cli/installer/fix_permissions.sh +++ b/deadend_cli/installer/fix_permissions.sh @@ -20,6 +20,15 @@ fi # Fix all shell scripts in playwright find "$INSTALL_DIR/lib/playwright" -type f \( -name "*.sh" -o -name "playwright*" \) -exec chmod +x {} \; 2>/dev/null +# Fix browser executables in .local-browsers +BROWSER_PATH="$INSTALL_DIR/lib/playwright/driver/package/.local-browsers" +if [ -d "$BROWSER_PATH" ]; then + echo "Fixing permissions for Playwright browsers..." + find "$BROWSER_PATH" -type f \( -name "chrome-headless-shell" -o -name "chrome-headless-shell*" -o -name "chrome*" -o -name "chromium*" \) -exec chmod +x {} \; 2>/dev/null || true + # Also fix permissions in subdirectories + find "$BROWSER_PATH" -type d -name "*chrome*" -exec find {} -type f -exec chmod +x {} \; \; 2>/dev/null || true +fi + # Fix any other executables that might need it find "$INSTALL_DIR/lib" -type f \( -name "node" -o -name "*.so" \) -exec chmod +x {} \; 2>/dev/null diff --git a/deadend_cli/installer/install_playwright_browsers.sh b/deadend_cli/installer/install_playwright_browsers.sh index 9cb5da4b..dfe06a82 100755 --- a/deadend_cli/installer/install_playwright_browsers.sh +++ b/deadend_cli/installer/install_playwright_browsers.sh @@ -32,49 +32,100 @@ if [ "$IS_MACOS" = false ]; then fi python3 -m pip install playwright $PIP_FLAGS -# First, install browsers to default location to get the version -python3 -m playwright install chromium +# Set PLAYWRIGHT_BROWSERS_PATH to install directly to target location +export PLAYWRIGHT_BROWSERS_PATH="$BROWSER_PATH" -# Find the installed chromium version -PLAYWRIGHT_CACHE="${HOME}/.cache/ms-playwright" -CHROMIUM_DIR=$(find "$PLAYWRIGHT_CACHE" -maxdepth 1 -type d -name "chromium-*" 2>/dev/null | head -n 1) +# Install chromium_headless_shell (the headless browser Playwright uses) +echo "Installing chromium_headless_shell to $BROWSER_PATH..." +python3 -m playwright install chromium_headless_shell -if [ -z "$CHROMIUM_DIR" ]; then - # Try alternative location (macOS) - PLAYWRIGHT_CACHE="${HOME}/Library/Caches/ms-playwright" - CHROMIUM_DIR=$(find "$PLAYWRIGHT_CACHE" -maxdepth 1 -type d -name "chromium-*" 2>/dev/null | head -n 1) -fi +# Target version - must be exactly 1208 +TARGET_VERSION="1208" +TARGET_DIR_NAME="chromium_headless_shell-$TARGET_VERSION" +TARGET_DIR="$BROWSER_PATH/$TARGET_DIR_NAME" -if [ -n "$CHROMIUM_DIR" ]; then - CHROMIUM_VERSION=$(basename "$CHROMIUM_DIR" | sed 's/chromium-//') - echo "Found Chromium version: $CHROMIUM_VERSION" - - # Copy to the target location with the expected name format - TARGET_DIR="$BROWSER_PATH/chromium_headless_shell-$CHROMIUM_VERSION" - mkdir -p "$TARGET_DIR" - cp -r "$CHROMIUM_DIR"/* "$TARGET_DIR/" +# Verify installation +if [ -d "$BROWSER_PATH" ]; then + echo "Browser installation successful" + echo "Browser directory contents:" + ls -la "$BROWSER_PATH" - echo "Copied Chromium $CHROMIUM_VERSION to $TARGET_DIR" - echo "Browser files:" - ls -la "$TARGET_DIR" | head -10 -else - echo "Warning: Could not find installed Chromium browser" - echo "Attempting to install directly to target location..." + # Check for chromium_headless_shell directory (any version) + HEADLESS_SHELL_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium_headless_shell-*" | head -n 1) - # Set PLAYWRIGHT_BROWSERS_PATH and try installing again - export PLAYWRIGHT_BROWSERS_PATH="$BROWSER_PATH" - python3 -m playwright install chromium + # Also check for chromium directory as fallback + if [ -z "$HEADLESS_SHELL_DIR" ]; then + CHROMIUM_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium-*" | head -n 1) + if [ -n "$CHROMIUM_DIR" ]; then + echo "Found chromium directory, will use it to create $TARGET_DIR_NAME" + HEADLESS_SHELL_DIR="$CHROMIUM_DIR" + fi + fi - # Check if it worked - if [ -d "$BROWSER_PATH" ]; then - echo "Browser installation to target location successful" - ls -la "$BROWSER_PATH" - # Rename if needed + if [ -n "$HEADLESS_SHELL_DIR" ]; then + HEADLESS_SHELL_NAME=$(basename "$HEADLESS_SHELL_DIR") + echo "Found browser directory: $HEADLESS_SHELL_NAME" + + # Rename or copy to the exact version name (chromium_headless_shell-1208) + if [ "$HEADLESS_SHELL_NAME" != "$TARGET_DIR_NAME" ]; then + echo "Renaming $HEADLESS_SHELL_NAME to $TARGET_DIR_NAME (version 1208)" + if [ -d "$TARGET_DIR" ]; then + echo "Target directory already exists, removing it first..." + rm -rf "$TARGET_DIR" + fi + mv "$HEADLESS_SHELL_DIR" "$TARGET_DIR" + echo "✓ Successfully renamed to $TARGET_DIR_NAME" + else + echo "✓ Directory already has correct name: $TARGET_DIR_NAME" + fi + + # Verify the target directory exists + if [ -d "$TARGET_DIR" ]; then + echo "Browser executable check:" + find "$TARGET_DIR" -type f -name "chrome-headless-shell" -o -name "chrome-headless-shell*" | head -5 || echo "Checking for browser executables..." + find "$TARGET_DIR" -type d -name "*chrome*" | head -5 || echo "Checking for browser directories..." + + # Fix permissions on browser executables + echo "Fixing permissions on browser executables..." + find "$TARGET_DIR" -type f \( -name "chrome-headless-shell" -o -name "chrome-headless-shell*" -o -name "chrome*" -o -name "chromium*" \) -exec chmod +x {} \; 2>/dev/null || true + find "$TARGET_DIR" -type d -name "*chrome*" -exec find {} -type f -exec chmod +x {} \; \; 2>/dev/null || true + else + echo "Error: Target directory $TARGET_DIR_NAME was not created" + exit 1 + fi + else + echo "Warning: No chromium_headless_shell or chromium directory found" + echo "Trying to find any chromium-related directories..." + find "$BROWSER_PATH" -maxdepth 1 -type d | head -10 + + # Try installing regular chromium as fallback + echo "Attempting to install regular chromium as fallback..." + python3 -m playwright install chromium + + # Check if chromium was installed CHROMIUM_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium-*" | head -n 1) - if [ -n "$CHROMIUM_DIR" ] && [[ "$CHROMIUM_DIR" != *"chromium_headless_shell"* ]]; then - CHROMIUM_VERSION=$(basename "$CHROMIUM_DIR" | sed 's/chromium-//') - mv "$CHROMIUM_DIR" "$BROWSER_PATH/chromium_headless_shell-$CHROMIUM_VERSION" - echo "Renamed to chromium_headless_shell-$CHROMIUM_VERSION" + if [ -n "$CHROMIUM_DIR" ]; then + echo "Found chromium directory, creating $TARGET_DIR_NAME from it" + if [ -d "$TARGET_DIR" ]; then + rm -rf "$TARGET_DIR" + fi + cp -r "$CHROMIUM_DIR" "$TARGET_DIR" + echo "✓ Created $TARGET_DIR_NAME from chromium installation" + # Fix permissions + find "$TARGET_DIR" -type f \( -name "chrome*" -o -name "chromium*" \) -exec chmod +x {} \; 2>/dev/null || true + else + echo "Error: Could not find chromium installation after fallback attempt" + exit 1 fi fi + + # Final verification that the target directory exists with the correct name + if [ ! -d "$TARGET_DIR" ]; then + echo "Error: Final verification failed - $TARGET_DIR_NAME does not exist" + exit 1 + fi + echo "✓ Final verification: $TARGET_DIR_NAME exists and is ready" +else + echo "Error: Browser installation failed - directory not created" + exit 1 fi diff --git a/install.sh b/install.sh old mode 100644 new mode 100755 index 3d87d14f..25ad00e2 --- a/install.sh +++ b/install.sh @@ -105,58 +105,89 @@ get_latest_version() { # Install install() { - echo -e "${GREEN}Installing Deadend CLI Server ${VERSION} for ${PLATFORM}...${NC}" + echo -e "${GREEN}Installing Deadend CLI ${VERSION} for ${PLATFORM}...${NC}" # Create temporary directory TEMP_DIR=$(mktemp -d) trap "rm -rf $TEMP_DIR" EXIT - # Download the release - DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${VERSION}/${PACKAGE_NAME}.tar.gz" - echo -e "${YELLOW}Downloading from: ${DOWNLOAD_URL}${NC}" + # Determine CLI package name + if [ "$PLATFORM" == "linux" ]; then + CLI_PACKAGE_NAME="deadend-cli-linux-x86_64" + else + CLI_PACKAGE_NAME="deadend-cli-macos-aarch64" + fi - if ! curl -fsSL -o "${TEMP_DIR}/${PACKAGE_NAME}.tar.gz" "$DOWNLOAD_URL"; then - echo -e "${RED}Error: Failed to download release${NC}" + # Download the server package + SERVER_DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${VERSION}/${PACKAGE_NAME}.tar.gz" + echo -e "${YELLOW}Downloading server package...${NC}" + echo "" + + if ! curl -fSL --progress-bar -o "${TEMP_DIR}/${PACKAGE_NAME}.tar.gz" "$SERVER_DOWNLOAD_URL"; then + echo -e "${RED}Error: Failed to download server package${NC}" exit 1 fi + echo "" - # Verify checksum if available - CHECKSUM_URL="https://github.com/${REPO}/releases/download/${VERSION}/${PACKAGE_NAME}.tar.gz.sha256" - if curl -fsSL -o "${TEMP_DIR}/${PACKAGE_NAME}.tar.gz.sha256" "$CHECKSUM_URL" 2>/dev/null; then - echo -e "${YELLOW}Verifying checksum...${NC}" - cd "$TEMP_DIR" - # Fix checksum file if it contains a path - replace with just the filename - if grep -q "/" "${PACKAGE_NAME}.tar.gz.sha256" 2>/dev/null; then - # Extract hash and filename, then rewrite with just filename - hash=$(awk '{print $1}' "${PACKAGE_NAME}.tar.gz.sha256" | head -1) - echo "${hash} ${PACKAGE_NAME}.tar.gz" > "${PACKAGE_NAME}.tar.gz.sha256" - fi - if command -v sha256sum >/dev/null 2>&1; then - sha256sum -c "${PACKAGE_NAME}.tar.gz.sha256" || { - echo -e "${RED}Error: Checksum verification failed${NC}" - exit 1 - } - elif command -v shasum >/dev/null 2>&1; then - shasum -a 256 -c "${PACKAGE_NAME}.tar.gz.sha256" || { - echo -e "${RED}Error: Checksum verification failed${NC}" - exit 1 - } - fi - echo -e "${GREEN}Checksum verified${NC}" - else - echo -e "${YELLOW}Warning: Checksum file not found, skipping verification${NC}" + # Download the CLI binary + CLI_DOWNLOAD_URL="https://github.com/${REPO}/releases/download/${VERSION}/${CLI_PACKAGE_NAME}.tar.gz" + echo -e "${YELLOW}Downloading CLI binary...${NC}" + echo "" + + if ! curl -fSL --progress-bar -o "${TEMP_DIR}/${CLI_PACKAGE_NAME}.tar.gz" "$CLI_DOWNLOAD_URL"; then + echo -e "${RED}Error: Failed to download CLI package${NC}" + exit 1 fi + echo "" + echo "" + + # Verify checksums if available + verify_checksum() { + local file="$1" + local checksum_url="https://github.com/${REPO}/releases/download/${VERSION}/${file}.sha256" + if curl -fsSL --progress-bar -o "${TEMP_DIR}/${file}.sha256" "$checksum_url" 2>/dev/null; then + cd "$TEMP_DIR" + # Fix checksum file if it contains a path - replace with just the filename + if grep -q "/" "${file}.sha256" 2>/dev/null; then + hash=$(awk '{print $1}' "${file}.sha256" | head -1) + echo "${hash} ${file}" > "${file}.sha256" + fi + if command -v sha256sum >/dev/null 2>&1; then + sha256sum -c "${file}.sha256" || return 1 + elif command -v shasum >/dev/null 2>&1; then + shasum -a 256 -c "${file}.sha256" || return 1 + fi + return 0 + fi + return 2 + } + + echo -e "${YELLOW}Verifying checksums...${NC}" + verify_checksum "${PACKAGE_NAME}.tar.gz" + case $? in + 0) echo -e "${GREEN}Server package checksum verified${NC}" ;; + 1) echo -e "${RED}Error: Server package checksum verification failed${NC}"; exit 1 ;; + 2) echo -e "${YELLOW}Warning: Server package checksum file not found, skipping verification${NC}" ;; + esac + + verify_checksum "${CLI_PACKAGE_NAME}.tar.gz" + case $? in + 0) echo -e "${GREEN}CLI package checksum verified${NC}" ;; + 1) echo -e "${RED}Error: CLI package checksum verification failed${NC}"; exit 1 ;; + 2) echo -e "${YELLOW}Warning: CLI package checksum file not found, skipping verification${NC}" ;; + esac - # Extract - echo -e "${YELLOW}Extracting package...${NC}" + # Extract packages + echo -e "${YELLOW}Extracting packages...${NC}" cd "$TEMP_DIR" tar -xzf "${PACKAGE_NAME}.tar.gz" + tar -xzf "${CLI_PACKAGE_NAME}.tar.gz" - # Create installation directory - echo -e "${YELLOW}Installing to ${INSTALL_DIR}...${NC}" + # Install server package + echo -e "${YELLOW}Installing server to ${INSTALL_DIR}...${NC}" mkdir -p "$INSTALL_DIR" - # Copy entire package contents (includes deadend binary, deadend.sh, lib/, etc.) + # Copy entire server package contents (includes deadend binary, deadend.sh, lib/, etc.) if [ -d "${PACKAGE_NAME}" ]; then cp -r "${PACKAGE_NAME}"/* "${INSTALL_DIR}/" chmod +x "${INSTALL_DIR}/deadend" 2>/dev/null || true @@ -167,19 +198,83 @@ install() { chmod +x "${INSTALL_DIR}/lib/playwright/driver/node" fi - echo -e "${GREEN}Package installed to ${INSTALL_DIR}${NC}" + echo -e "${GREEN}Server installed to ${INSTALL_DIR}${NC}" else - echo -e "${RED}Error: Package directory not found${NC}" + echo -e "${RED}Error: Server package directory not found${NC}" exit 1 fi + # Install CLI binary to PATH + echo -e "${YELLOW}Installing CLI binary...${NC}" + + # Determine the best location for the CLI binary + if [ "$PLATFORM" == "linux" ]; then + CLI_BIN_DIR="$HOME/.local/bin" + else + # macOS: use ~/.local/bin or /usr/local/bin + CLI_BIN_DIR="$HOME/.local/bin" + # Try /usr/local/bin if ~/.local/bin doesn't exist and we have write access + if [ ! -d "$HOME/.local" ] && [ -w "/usr/local/bin" ]; then + CLI_BIN_DIR="/usr/local/bin" + fi + fi + + mkdir -p "$CLI_BIN_DIR" + + # Find and copy the CLI binary + if [ -d "${CLI_PACKAGE_NAME}" ]; then + CLI_BINARY="" + # Look for the binary (could be named deadend-cli or deadend) + for bin in "${CLI_PACKAGE_NAME}"/deadend-cli "${CLI_PACKAGE_NAME}"/deadend "${CLI_PACKAGE_NAME}"/*; do + if [ -f "$bin" ] && [ -x "$bin" ] || [ -f "$bin" ]; then + CLI_BINARY="$bin" + break + fi + done + + if [ -n "$CLI_BINARY" ] && [ -f "$CLI_BINARY" ]; then + cp "$CLI_BINARY" "${CLI_BIN_DIR}/deadend" + chmod +x "${CLI_BIN_DIR}/deadend" + echo -e "${GREEN}CLI binary installed to ${CLI_BIN_DIR}/deadend${NC}" + else + echo -e "${YELLOW}Warning: Could not find CLI binary in package${NC}" + fi + else + echo -e "${RED}Error: CLI package directory not found${NC}" + exit 1 + fi + + # Check if CLI_BIN_DIR is in PATH + if [[ ":$PATH:" != *":$CLI_BIN_DIR:"* ]]; then + echo "" + echo -e "${YELLOW}Note: ${CLI_BIN_DIR} is not in your PATH${NC}" + echo -e "${YELLOW}Add it by running:${NC}" + echo -e " export PATH=\"${CLI_BIN_DIR}:\$PATH\"" + echo "" + echo -e "${YELLOW}Or add to your shell configuration file:${NC}" + if [ "$PLATFORM" == "linux" ]; then + echo -e " echo 'export PATH=\"${CLI_BIN_DIR}:\$PATH\"' >> ~/.bashrc" + else + echo -e " echo 'export PATH=\"${CLI_BIN_DIR}:\$PATH\"' >> ~/.zshrc" + fi + fi + echo "" echo -e "${GREEN}Installation complete!${NC}" echo "" echo "The Deadend CLI server is installed at:" echo " ${INSTALL_DIR}/deadend.sh" echo "" - echo "You can set DEADEND_RPC_BINARY environment variable to use a custom path:" + if [ -f "${CLI_BIN_DIR}/deadend" ]; then + echo "The Deadend CLI command is available at:" + echo " ${CLI_BIN_DIR}/deadend" + if [[ ":$PATH:" == *":$CLI_BIN_DIR:"* ]]; then + echo "" + echo "You can now run: deadend" + fi + fi + echo "" + echo "You can set DEADEND_RPC_BINARY environment variable to use a custom server path:" echo " export DEADEND_RPC_BINARY=\"${INSTALL_DIR}/deadend.sh\"" echo "" } From 706c31c9cd67b7d710a2e2c9dbf6a9ac25f72347 Mon Sep 17 00:00:00 2001 From: Yassine Bargach Date: Sun, 8 Feb 2026 13:32:42 +0100 Subject: [PATCH 2/3] playwright issue --- deadend_cli/installer/install_playwright_browsers.sh | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/deadend_cli/installer/install_playwright_browsers.sh b/deadend_cli/installer/install_playwright_browsers.sh index dfe06a82..b8290e47 100755 --- a/deadend_cli/installer/install_playwright_browsers.sh +++ b/deadend_cli/installer/install_playwright_browsers.sh @@ -35,9 +35,9 @@ python3 -m pip install playwright $PIP_FLAGS # Set PLAYWRIGHT_BROWSERS_PATH to install directly to target location export PLAYWRIGHT_BROWSERS_PATH="$BROWSER_PATH" -# Install chromium_headless_shell (the headless browser Playwright uses) -echo "Installing chromium_headless_shell to $BROWSER_PATH..." -python3 -m playwright install chromium_headless_shell +# Install chromium-headless-shell (the headless browser Playwright uses) +echo "Installing chromium-headless-shell to $BROWSER_PATH..." +python3 -m playwright install chromium-headless-shell # Target version - must be exactly 1208 TARGET_VERSION="1208" @@ -50,8 +50,9 @@ if [ -d "$BROWSER_PATH" ]; then echo "Browser directory contents:" ls -la "$BROWSER_PATH" - # Check for chromium_headless_shell directory (any version) - HEADLESS_SHELL_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d -name "chromium_headless_shell-*" | head -n 1) + # Check for chromium-headless-shell directory (Playwright creates it with hyphens) + # Also check for chromium_headless_shell (with underscores) in case it was renamed + HEADLESS_SHELL_DIR=$(find "$BROWSER_PATH" -maxdepth 1 -type d \( -name "chromium-headless-shell-*" -o -name "chromium_headless_shell-*" \) | head -n 1) # Also check for chromium directory as fallback if [ -z "$HEADLESS_SHELL_DIR" ]; then From 50d02af1505266b3411d4ce67490e9a727db55be Mon Sep 17 00:00:00 2001 From: Yassine Bargach Date: Sun, 8 Feb 2026 18:48:40 +0100 Subject: [PATCH 3/3] README.md update, installation and release ops --- README.md | 42 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7603a964..558d8cfe 100644 --- a/README.md +++ b/README.md @@ -56,20 +56,43 @@ The framework focuses on **intelligent security analysis** through: ### Prerequisites - Docker (required) -- Python 3.11+ -- Playwright: `playwright install` +- curl (for installation script) ### Installation + +**Recommended: Install from release (Linux x86_64 / macOS ARM64)** + ```bash -# Install via pipx (recommended) -pipx install deadend_cli +# Install latest release +curl -fsSL https://raw.githubusercontent.com/xoxruns/deadend-cli/main/install.sh | bash -# Or build from source +# Or install a specific version +curl -fsSL https://raw.githubusercontent.com/xoxruns/deadend-cli/main/install.sh | bash -s -- --version v1.0.0 + +# Custom installation directory (default: ~/.cache/server) +curl -fsSL https://raw.githubusercontent.com/xoxruns/deadend-cli/main/install.sh | bash -s -- --install-dir /path/to/install +``` + +The installer will: +- Download pre-built binaries for your platform +- Install the RPC server to `~/.cache/server` (or custom directory) +- Install the CLI binary to `~/.local/bin` (or `/usr/local/bin` on macOS) +- Set up Playwright browsers automatically + +**Alternative: Build from source** + +```bash git clone https://github.com/xoxruns/deadend-cli.git cd deadend-cli uv sync && uv build ``` +**Legacy: Install via pipx** + +```bash +pipx install deadend_cli +``` + ### First Run ```bash # Initialize configuration @@ -81,6 +104,12 @@ deadend chat \ --prompt "find SQL injection vulnerabilities" ``` +**Note:** If `deadend` is not found, ensure `~/.local/bin` is in your PATH: +```bash +export PATH="$HOME/.local/bin:$PATH" +# Add to ~/.bashrc or ~/.zshrc to make it permanent +``` + --- ## Usage Examples @@ -189,8 +218,9 @@ deadend chat --target URL --mode yolo - **Instructor**: Structured LLM outputs - **pgvector**: Vector database for context - **Pyodide/WebAssembly**: Python sandbox -- **Playwright**: HTTP request generation +- **Playwright**: HTTP request generation (bundled with browser binaries) - **Docker**: Shell command isolation +- **PyOxidizer**: Standalone binary packaging ---