> ## Documentation Index
> Fetch the complete documentation index at: https://docs.murmur.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Repo Hooks

> Run per-repo setup scripts — dependency installs, code generation, cache warming — automatically after clone and before the Murmur agent starts work.

Repos often need setup after cloning before an agent can work productively: `npm ci`, `go mod download`, code generation, writing local config. Without it, every agent burns its first minutes (and tokens) rediscovering and running your setup commands.

A **repo hook** is a Bash script committed to the repo itself that Murmur runs automatically on the VM after the repo is cloned and before the agent starts. No configuration, no spawn flags — committing the file enables it.

## The prepare-workspace hook

Create the hook at this exact path in your repo:

```
.murmur/hooks/prepare-workspace.sh
```

```bash theme={null}
# .murmur/hooks/prepare-workspace.sh
set -euo pipefail

npm ci
npm run codegen
cp .env.example .env
```

The hook runs:

* **Once per prepared workspace** — after all repos are cloned on their working branches, git identity and credentials are configured, and workspace plugins are installed; immediately before the agent process starts. It does not re-run when an agent wakes from sleep on the same VM. An agent resurrected onto a fresh VM prepares a fresh workspace and runs the hook again.
* **From the working branch** the agent will operate on — the hook version that runs is the one the agent's code will see, so a branch that changes the build system carries the matching hook change in the same commit.
* **With the repo's checkout directory as the working directory**, so relative paths resolve inside the repo.
* **Under `/bin/bash`** — no executable bit or shebang required. Bash is the contract.

In multi-repo workspaces, each repo's hook runs sequentially in workspace repo order.

## Environment

The hook sees the same environment as the agent itself:

| Variable             | Description                                                                               |
| -------------------- | ----------------------------------------------------------------------------------------- |
| `GH_TOKEN`           | GitHub token — `git` and `gh` are already authenticated, no setup needed                  |
| `MURMUR_SECRET_*`    | Your tenant, developer, and spawn-time secrets                                            |
| `MURMUR_HOOK`        | The hook point name (`prepare-workspace`), so shared helper scripts can branch on context |
| `MURMUR_WORKFLOW_ID` | The agent's workflow identifier                                                           |

Model API keys and file-mounted secrets are also available, exactly as the agent receives them.

## Failure semantics

Hooks fail loudly. If the hook exits non-zero, the spawn fails with an error naming the repo and the hook — the agent never starts in a workspace whose declared setup failed. There is no retry: fix the hook (or the setup it runs) and spawn again.

All hooks in a workspace share a **5-minute total budget**. A hook still running when the budget expires is killed and the spawn fails with a timeout error. Heavier setup belongs in a [custom image](/guides/custom-images) or startup script — bake the toolchain into the image, and use the hook only for the per-branch remainder.

Hook output streams to the VM's system log in real time, and the tail of the output is captured in the failure error so you can see why a hook failed.

## Organizing helper scripts

`.murmur/hooks/` is free-form. Murmur executes only the hook names it recognizes (`prepare-workspace.sh`) and ignores everything else, so you can organize sub-scripts however you want:

```
.murmur/hooks/
  prepare-workspace.sh
  lib/
    install-deps.sh
    seed-db.sh
```

```bash theme={null}
# .murmur/hooks/prepare-workspace.sh
set -euo pipefail
source "$(dirname "$0")/lib/install-deps.sh"
source "$(dirname "$0")/lib/seed-db.sh"
```

If a `.murmur/hooks/` directory exists but contains no recognized hook (for example, a misspelled file name), Murmur logs a warning rather than silently doing nothing.

## Guidelines

<Warning>
  Hook output lands in logs, and the failure tail is captured with the error. Never `echo` secrets, and never `set -x` around commands that take credentials in arguments.
</Warning>

* **Set up the workspace; don't mutate remotes.** The hook runs before Murmur's git/gh instrumentation is installed, so pushes or `gh` calls made from a hook won't generate PR tracking or timeline events. Save remote operations for the agent.
* **Keep it fast.** The hook delays agent start on every spawn. Anything stable across branches (toolchains, system packages, large dependency trees) belongs in a custom image; the hook is for what changes with the code.
* **Make it idempotent-friendly.** The hook runs once per prepared workspace, but a resurrected agent gets a fresh VM and runs it again — don't depend on state from a previous run.

## Hooks vs. startup scripts vs. custom images

| Mechanism          | Runs                                                 | Best for                                                              |
| ------------------ | ---------------------------------------------------- | --------------------------------------------------------------------- |
| **Repo hook**      | After clone, on the working branch, before the agent | Per-repo, per-branch setup: dependency install, codegen, local config |
| **Startup script** | At VM boot, before repos exist                       | Environment-level packages and tools, on every boot                   |
| **Custom image**   | At image bake time, frozen into the image            | Heavy, stable toolchains — zero per-spawn cost                        |
