Shadow Background Coding Agent

repository·main·Indexed 23 days ago

https://github.com/ishaan1013/shadow

An open-source background coding agent designed to understand and contribute to existing codebases. Shadow features a semantic code indexing system using Pinecone and tree-sitter, isolated execution environments called the 'Shadow Realm' (supporting local and remote modes via Kata QEMU and EKS), and a comprehensive tool system for file operations, terminal execution, and code search.

Tokens
14K
Snippets
30
Records
99
Agent score
79%

What's inside Shadow

  1. Understand Shadow execution modes

    main

    Shadow operates in two distinct execution modes, controlled by the NODE_ENV and AGENT_MODE environment variables:

    1. Local Mode: Executes commands directly on the host machine's filesystem.
    2. Remote Mode (For Deployment): Provides hardware-level isolation using Kata QEMU containers and Kubernetes orchestration. Note: Remote mode requires Amazon Linux 2023 nodes for Kata Containers compatibility.
  2. How the Shadow Code Indexing System works

    main

    The Shadow Code Indexing System converts a repository into a searchable semantic format for agents through a five-step pipeline:

    1. Graph Construction: Builds a semantic graph where GraphNode objects represent entities (files, classes, functions, documentation) and GraphEdge objects define relationships (e.g., CONTAINS, CALLS, DOCS_FOR).
    2. Chunking: Breaks large code blocks into smaller, semantically coherent chunks to fit within language model context windows.
    3. Embedding: Converts code chunks into high-dimensional vectors using embedding models (e.g., Jina or local transformers).
    4. Storage: Uploads vectors and metadata (file paths, node IDs) to a vector database, specifically Pinecone.
    5. Retrieval: Enables natural language queries by embedding the query and performing similarity searches against the Pinecone index.

    This process allows an agent to find code based on semantic meaning rather than simple keyword matching.

  3. Install and set up Shadow for development

    main
    To set up a local development environment for Shadow, ensure you have Node.js 22 and PostgreSQL installed. Follow these steps to clone, install dependencies, configure environment variables, and initialize the database.
  4. Use the search and replace tool for file modifications

    main

    The search and replace tool allows you to propose a modification to an existing file by replacing a specific old_string with a new_string.

    Constraints and Best Practices

    • Single Instance Only: The tool replaces exactly ONE occurrence per call. To modify multiple instances of the same string, you must make separate tool calls for each instance.
    • Uniqueness via Context: To ensure the correct instance is targeted, the old_string must be unique. You must include significant context to avoid accidental matches elsewhere in the file:
      • Include at least 3-5 lines of context BEFORE the target change point.
      • Include at least 3-5 lines of context AFTER the target change point.
      • Match all whitespace, indentation, and surrounding code exactly as it appears in the source file.
    • Verification Workflow:
      1. Identify if multiple instances of the target string exist.
      2. Gather unique context for each instance.
      3. Plan and execute separate tool calls for each unique instance.
  5. Configure environment variables for Local Mode

    main

    For a quick start in local mode without installing a GitHub App, use a GitHub Personal Access Token (PAT) with repo and read:org scopes. This allows the GitHub selector to work immediately.

    Note: Running ./setup-script.sh can automate this process.

    # apps/server/.env
    DATABASE_URL="postgres://postgres:@127.0.0.1:5432/shadow_dev"
    BETTER_AUTH_SECRET="dev-secret"
    GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx
    NODE_ENV=development
    AGENT_MODE=local
    WORKSPACE_DIR=/path/to/your/local/workspace
    
    # apps/frontend/.env.local
    NEXT_PUBLIC_SERVER_URL=http://localhost:4000
    NEXT_PUBLIC_VERCEL_ENV=development
    GITHUB_PERSONAL_ACCESS_TOKEN=ghp_xxx
    
    # packages/db/.env
    DATABASE_URL="postgres://postgres:@127.0.0.1:5432/shadow_dev"
    DIRECT_URL="postgres://postgres:@127.0.0.1:5432/shadow_dev"
  6. Deploy Shadow to AWS Remote Infrastructure

    main

    Shadow can be deployed to AWS using Amazon EKS with Kata QEMU containers for hardware-level VM isolation. The deployment process involves two main stages: setting up the remote infrastructure (EKS cluster) and then deploying the Shadow application itself.

    Prerequisites

    Before running deployment scripts, ensure you have configured your AWS SSO profile:

    aws configure sso --profile=YOUR_PROFILE_ID

    Deployment Steps

    1. Deploy the EKS Cluster with Kata Containers (Takes 25-35 minutes): Run the infrastructure deployment script to set up the EKS cluster, Kata QEMU runtime, and persistent storage.

      ./scripts/deploy-remote-infrastructure.sh
    2. Deploy the Shadow Application: Once the infrastructure is ready, deploy the complete platform.

      ./scripts/deploy-full-infrastructure.sh
    # Configure AWS SSO
    aws configure sso --profile=ID
    
    # Deploy infrastructure (25-35 minutes)
    ./scripts/deploy-remote-infrastructure.sh
    
    # Deploy complete platform
    ./scripts/deploy-full-infrastructure.sh
  7. Use the edit_file tool to rewrite or create files

    main

    The edit_file tool is used to either create a new file or rewrite an existing file by providing its complete content.

    Critical Requirements for usage:

    • Full Content Only: You must write out the ENTIRE file content. This includes all existing code you wish to keep, all imports, functions, variables, and any other necessary code blocks.
    • The code_edit field: This field is used to hold the complete new content of the file. It does not support partial diffs or line-based edits; it replaces the entire file.
    • Argument Order: You should specify the target_file argument before other arguments.

    Scenarios:

    • To create a new file: Provide the complete intended content of the file in the code_edit field.
    • To edit an existing file: You must provide the complete file content, including your changes, as the new version of the file.
  8. Use the grep_search tool for exact text or regex matches

    main

    The grep_search tool is designed for fast, exact regex searches using the ripgrep engine. It is preferred over semantic search when you know the exact symbol, function name, or text pattern you are looking for within specific directories or file types.

    Key Constraints and Behaviors

    • Match Type: Performs only exact regex searches. Do NOT attempt fuzzy or semantic matches.
    • Output Limit: Results are capped at 50 matches to prevent overwhelming the output.
    • Filtering: Use include or exclude patterns to filter the search scope by file type or specific paths.
    • Input Requirement: You must return only a valid regex pattern string.

    Regex Escaping Requirements

    When providing a search string, you must escape special regex characters using a backslash (\). The characters that require escaping include: (, ), [, ], {, }, +, *, ?, ^, $, |, ., and \.

    | Literal               | Regex Pattern            |
    |-----------------------|--------------------------|
    | function(             | function\\(              |
    | value[index]          | value\\[index\\]         |
    | file.txt               | file\\.txt                |
    | user\|admin            | user\\\|admin             |
    | path\\to\\file         | path\\\\to\\\\file         |
    | hello world           | hello world              |
    | foo\\(bar\\)          | foo\\\\(bar\\\\)          |
  9. Manage filesystem watchers for local mode

    main

    In local mode, Shadow uses LocalFileSystemWatcher to monitor workspace changes.

    • Lifecycle: A watcher is started automatically during createTools if a workspacePath is provided. It is mapped to the taskId.
    • Retrieval: Use getFileSystemWatcher(taskId) to access the active watcher for a task.
    • Cleanup: Use stopFileSystemWatcher(taskId) to stop a specific watcher, or stopAllFileSystemWatchers() to clear all active watchers during shutdown.
    • Monitoring: getFileSystemWatcherStats() returns the number of active watchers and their individual details.
  10. Manage MCP tools and connections

    main

    Shadow supports the Model Context Protocol (MCP).

    • Initialization: When createTools is called, an MCPManager is initialized and connections are established.
    • Tool Wrapping: MCP tools are automatically transformed using transformMCPToolName to ensure compatibility with the AI SDK. The createMCPToolWrapper also enforces a MAX_CONTEXT7_TOKENS limit (4000 tokens) on tools prefixed with context7: to prevent context overflow.
    • Cleanup: Use stopMCPManager(taskId) to close all active MCP connections for a task, or stopAllMCPManagers() for a graceful shutdown.
  11. Determine the GitHub authentication mode

    main

    The system switches between 'Personal Token Mode' and 'GitHub App Mode' based on the environment and configuration. You can use isPersonalTokenMode() to check which mode is currently active.

    Mode Logic:

    • Personal Token Mode: Active if NEXT_PUBLIC_VERCEL_ENV is NOT production, a PERSONAL_GITHUB_TOKEN or GITHUB_TOKEN is present, and NEXT_PUBLIC_FORCE_GITHUB_APP is not set to true.
    • GitHub App Mode: Active in production, or if NEXT_PUBLIC_FORCE_GITHUB_APP is set to true.

    Relevant Environment Variables:

    • NEXT_PUBLIC_VERCEL_ENV
    • GITHUB_PERSONAL_ACCESS_TOKEN / GITHUB_TOKEN
    • NEXT_PUBLIC_FORCE_GITHUB_APP (set to "true" to force App mode)
  12. How dependency installation works in TaskInitializationEngine

    main

    The executeInstallDependencies step automatically detects the project type and uses the appropriate package manager. It checks for the following files in the workspace:

    • Node.js:

      • bun.lockb $\rightarrow$ bun install
      • pnpm-lock.yaml $\rightarrow$ pnpm install
      • yarn.lock $\rightarrow$ yarn install
      • package.json (default) $\rightarrow$ npm install
    • Python:

      • requirements.txt $\rightarrow$ pip install -r requirements.txt
      • pyproject.toml $\rightarrow$ pip install -e .