Lifecycle Hooks

Run rift init inside a git project to create a rift.yaml at the repo root. This file configures per-project settings and lifecycle hooks.

Project Overrides

You can override the global editor and agent settings on a per-project basis:

editor: cursor
agent: claude
hooks:
  open: "bun install"
  • editor — the editor command to use for this project (e.g. code, cursor, windsurf). Overrides the global config.
  • agent — the coding agent command to use for this project (e.g. claude, copilot, codex). Overrides the global config.

Hooks

Run commands on lifecycle events:

hooks:
  open: "bun install"
  jump: "bun install"
  close: "echo closing worktree"
  purge: "echo purging all"
  • open — runs after a new worktree is created
  • jump — runs after switching to a worktree
  • close — runs before a worktree is removed
  • purge — runs before each worktree is removed during purge

How Hooks Work

  • Hooks are defined in rift.yaml at the root of your repository.
  • Each hook value is passed to bash -c, so you can use any shell syntax.
  • Hooks run synchronously — Rift waits for the command to finish before continuing.
  • Hook failures are not blocking — if a hook exits with a non-zero code, Rift logs the hook execution but continues with the operation. A failing open hook will not prevent the worktree from being created.
  • The working directory is the worktree directory (e.g. ~/.rift/worktrees/my-project/bold-ant).
  • The environment variable RIFT_WORKTREE is set to the worktree name (e.g. bold-ant).

Common Patterns

Install dependencies on open/jump:

hooks:
  open: "npm install"
  jump: "npm install"

Chain multiple commands:

hooks:
  open: "npm install && npm run db:migrate"

Call a script file:

hooks:
  open: "bash scripts/bootstrap.sh"

This keeps complex setup logic out of rift.yaml and in a version-controlled script.

The Bootstrap Pattern

When multiple worktrees run dev servers simultaneously, they all compete for the same default ports. The bootstrap pattern solves this by running a command on the open and jump hooks that derives a deterministic port from the worktree name — the same worktree always gets the same port.

Bash script example

Create a bootstrap script manually or follow the framework guides:

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

# Derive a deterministic port from the worktree name.
# The same worktree always gets the same port (range 3000–9999).
hash=$(echo -n "$RIFT_WORKTREE" | shasum | tr -d 'a-f ' | cut -c1-4)
PORT=$(( (hash % 7000) + 3000 ))

echo "PORT=$PORT" > .env
echo "Assigned port $PORT for worktree '$RIFT_WORKTREE'"

The formula strips hex letters from the SHA hash, takes the first 4 digits, and maps them into the range 3000–9999.

Custom commands

The hook command doesn’t have to be a bash script — it can be any command your project supports. For example:

hooks:
  open: "npm run bootstrap"
  jump: "npm run bootstrap"
hooks:
  open: "node scripts/setup.js"
  jump: "node scripts/setup.js"

The RIFT_WORKTREE environment variable is available in all hook commands.

Multiple ports

If your project runs several services (frontend, API, database), derive multiple ports from the same base:

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

hash=$(echo -n "$RIFT_WORKTREE" | shasum | tr -d 'a-f ' | cut -c1-4)
BASE=$(( (hash % 7000) + 3000 ))

cat > .env <<EOF
PORT=$BASE
API_PORT=$(( BASE + 1 ))
DB_PORT=$(( BASE + 2 ))
EOF

echo "Assigned ports $BASE, $(( BASE + 1 )), $(( BASE + 2 )) for worktree '$RIFT_WORKTREE'"

Wiring it up

Add the hook command to your rift.yaml:

hooks:
  open: "bash scripts/bootstrap.sh"
  jump: "bash scripts/bootstrap.sh"

Running on both open and jump ensures the .env file is always present, even if the worktree was created before the script existed.

.gitignore

The generated .env file is worktree-specific and should not be committed:

# .gitignore
.env

Next steps

See the framework guides for step-by-step examples of reading the assigned port, configuring databases, and wiring up hooks, and the Docker Compose guide for isolating containerized services across worktrees.