# Repository Lifecycle Scripts in Background Agents: Understanding setup.sh and start.sh

> Understand repository lifecycle scripts setup.sh and start.sh. Learn how these background agents scripts handle one-time provisioning and per-session runtime initialization for efficient deployments.

- Repository: [Cole Murray/background-agents](https://github.com/ColeMurray/background-agents)
- Tags: internals
- Published: 2026-07-13

---

**Background Agents utilizes a two-step boot process where [`.openinspect/setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/.openinspect/setup.sh) handles one-time provisioning during image builds while [`.openinspect/start.sh`](https://github.com/ColeMurray/background-agents/blob/main/.openinspect/start.sh) manages per-session runtime initialization in sandboxed Modal environments.**

The ColeMurray/background-agents repository orchestrates autonomous coding agents inside isolated Modal sandboxes. Understanding the repository lifecycle scripts is essential for customizing your agent's environment, as these Bash scripts control exactly how dependencies are installed, shared packages are built, and long-running services are started before any agent code executes.

## The Setup Phase: Provisioning with setup.sh

The [`.openinspect/setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/.openinspect/setup.sh) script runs **once** during repository image builds or the first time a fresh session initializes. Located at [`/.openinspect/setup.sh`](https://github.com/ColeMurray/background-agents/blob/main//.openinspect/setup.sh), this script prepares the entire repository for execution by installing tooling, building dependencies, and validating the environment.

### Prerequisite Validation and Node.js Requirements

The script begins with strict prerequisite checks to ensure the environment meets baseline requirements. It verifies that `node` and `npm` are available and enforces **Node.js ≥ 20** for compatibility with the modern TypeScript toolchain. These checks ensure that subsequent build steps fail fast with clear error messages rather than obscure dependency failures.

### Dependency Installation and Shared Package Builds

After validation, the script executes `npm install`, which simultaneously triggers **Husky’s `prepare` hook** to install Git hooks. The provisioning process prioritizes building `@open-inspect/shared` first, as every other package in the monorepo depends on this shared library. The script explicitly verifies that the pre-commit hook is installed, running `npx husky` if missing.

### Optional Python Environment Configuration

When the `packages/modal-infra` directory exists and **Python ≥ 3.12** is detected on the host, the script automatically configures a Python environment. It prefers `uv` for lockfile synchronization if available, falling back to a traditional `venv` combined with `pip install -e` workflow. This ensures the Modal infrastructure package is ready for agents requiring Python tooling.

### Type Checking and Idempotency

The script concludes by running `npm run typecheck` across all packages and warning if any package still requires building. Designed to be **idempotent**, [`setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/setup.sh) can be re-run safely without side effects. Failures during image-build mode are treated as fatal errors, while failures during fresh sessions are logged but allow the session to continue starting.

## The Runtime Phase: Initialization with start.sh

After provisioning completes, the boot sequence proceeds to the optional start phase. According to the source code in [`packages/control-plane/src/sandbox/lifecycle/decisions.ts`](https://github.com/ColeMurray/background-agents/blob/main/packages/control-plane/src/sandbox/lifecycle/decisions.ts) (line 491), the script at [`/.openinspect/start.sh`](https://github.com/ColeMurray/background-agents/blob/main//.openinspect/start.sh) executes **once per session** after the repository image has been restored.

### Long-Running Processes and Development Servers

When present, [`start.sh`](https://github.com/ColeMurray/background-agents/blob/main/start.sh) is responsible for launching any long-running processes the agent requires. Common use cases include starting local development servers with commands like `npm run dev -w @open-inspect/web`, initializing background workers, running database migrations, or spawning custom service daemons. The platform skips this step entirely if the file is missing.

### Environment Variable Export

The script typically exports critical environment variables that subsequent components rely on. Variables defined here become available to the `opencode` bridge and the Modal sandbox connection, ensuring proper communication between the agent and its host environment.

## Implementation Examples

Both scripts follow defensive Bash conventions using `set -euo pipefail` to ensure strict error handling.

### Customizing setup.sh for Additional Tooling

The following snippet demonstrates installing a global CLI tool and building a new package:

```bash
#!/usr/bin/env bash
set -euo pipefail

# Helpers

info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }

info "Installing additional CLI"
npm install -g my-cli-tool

info "Building new package @open-inspect/my-package"
npm run build -w @open-inspect/my-package

```

### Configuring start.sh for Development Servers

This example launches a web server and exposes its port to the sandbox:

```bash
#!/usr/bin/env bash
set -euo pipefail

info() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }

info "Starting local web server"
npm run dev -w @open-inspect/web &
SERVER_PID=$!

# Export the port so the sandbox bridge can connect

export WEB_PORT=3000

# Wait for the server to exit (or trap signals for graceful shutdown)

wait $SERVER_PID

```

## Boot Sequence Integration

These scripts fit into a specific execution order defined in the Background Agents platform. The complete boot sequence flows as:

1. **[`.openinspect/setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/.openinspect/setup.sh)** – Provisioning and dependency installation
2. **[`.openinspect/start.sh`](https://github.com/ColeMurray/background-agents/blob/main/.openinspect/start.sh)** – Runtime initialization (if present)
3. **`opencode`** – Agent code execution
4. **Bridge connection** – Modal sandbox communication established

This architecture ensures that every sandboxed session starts from a reproducible, fully-provisioned state before the actual agent logic begins execution.

## Summary

- **[`.openinspect/setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/.openinspect/setup.sh)** runs once during image builds to install Node.js dependencies, build the `@open-inspect/shared` package, configure Python ≥ 3.12 environments using `uv` or `venv`, and verify Git hooks.
- **[`.openinspect/start.sh`](https://github.com/ColeMurray/background-agents/blob/main/.openinspect/start.sh)** runs once per session to launch long-running processes like development servers and export environment variables required by the Modal sandbox.
- Both scripts use `set -euo pipefail` for fail-safe execution and are referenced in [`packages/control-plane/src/sandbox/lifecycle/decisions.ts`](https://github.com/ColeMurray/background-agents/blob/main/packages/control-plane/src/sandbox/lifecycle/decisions.ts) at line 491.
- The setup script is idempotent and safe to re-run, while the start script is optional and skipped if missing.

## Frequently Asked Questions

### What is the difference between setup.sh and start.sh in Background Agents?

**[`setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/setup.sh)** executes during image builds and first-run sessions to install dependencies and build shared packages, while **[`start.sh`](https://github.com/ColeMurray/background-agents/blob/main/start.sh)** runs after provisioning to initialize long-running services for that specific session. The setup script prepares the environment once; the start script configures the runtime for each individual agent execution.

### How do I add Python dependencies to my Background Agents repository?

Place your Python code in `packages/modal-infra` and ensure Python ≥ 3.12 is available. The [`setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/setup.sh) script automatically detects this directory and installs dependencies using **uv** (preferred) or falls back to `venv` plus `pip install -e`. You can also manually activate the environment in [`start.sh`](https://github.com/ColeMurray/background-agents/blob/main/start.sh) if you need Python services running during the session.

### What happens if start.sh is missing from my repository?

The platform treats [`start.sh`](https://github.com/ColeMurray/background-agents/blob/main/start.sh) as optional. If the file does not exist at [`/.openinspect/start.sh`](https://github.com/ColeMurray/background-agents/blob/main//.openinspect/start.sh), the boot sequence skips the runtime initialization phase and proceeds directly to executing the agent code. This is the default behavior for repositories that do not require custom background processes.

### Is setup.sh idempotent and safe to run multiple times?

Yes, the [`setup.sh`](https://github.com/ColeMurray/background-agents/blob/main/setup.sh) script is designed to be **idempotent**. You can safely re-run it without causing duplicate installations or build errors. The script validates existing installations and only performs destructive operations when necessary, making it safe for both local development and CI/CD pipelines.