gwm-cli 1.0.0

git worktree manager — TUI + CLI, native libgit2, per-repo bootstrap
Documentation
---
title: Regex guards
description: Deny-list patterns on copied files — the original "no AWS RDS in .env" incident, generalised.
---

# Regex guards

`[[bootstrap.guard]]` rules vet each file produced by stage 1 of the [bootstrap pipeline](/configuration/bootstrap) against a list of regex deny-patterns. A match triggers either an abort or a substitution from a known-good fallback.

## the origin story

The original incident: someone created a worktree from a repo with `.env` pointing at the **production** AWS RDS host, then ran `php artisan migrate:fresh --seed` in the worktree thinking it was the local DB. The migration ran against prod.

The fix was institutional: never copy a `.env` blindly across worktrees. The mechanism is `[[bootstrap.guard]]`.

## schema

```toml
[[bootstrap.guard]]
name = "no-aws-rds"
deny_patterns = ["amazonaws\\.com", "\\.rds\\."]
on_match      = "seed-from-example"        # or "abort"
example_file  = ".env.example"             # required when on_match=seed-from-example
```

| Field           | Type            | Default   | Meaning                                                                                |
|:----------------|:----------------|:----------|:---------------------------------------------------------------------------------------|
| `name`          | string          || referenced by `[[bootstrap.copy]].guards = [...]`                                       |
| `deny_patterns` | list of strings | `[]`      | Rust regex patterns (`regex` crate syntax). Matches anywhere in the file are flagged.   |
| `on_match`     | string          | `"abort"` | `"abort"` or `"seed-from-example"`                                                      |
| `example_file` | string          | none      | path (relative to main checkout) of the file to substitute when `on_match=seed-from-example` |

## wiring a guard into a copy

The guard runs only when a `[[bootstrap.copy]]` step references it by name:

```toml
[[bootstrap.copy]]
from = ".env"
to   = ".env"
required = false
guards = ["no-aws-rds"]            # ← referenced here
```

A guard with no copy references it is dead config — `gwm doctor` (check #2) does not flag this (yet), so audit by hand or run `grep guards .gwm.toml` to spot orphans.

## `on_match` semantics

### `abort` (default)

A match halts the entire bootstrap with `✗`. The worktree itself was already created (stage 1 succeeded), so gwm rolls it back: removes the worktree directory and the branch.

```
bootstrap report:
  ✗ guard no-aws-rds on .env
      pattern 'amazonaws\.com' matched on line 12
      → bootstrap aborted, worktree rolled back
```

The user sees the offending pattern, the line, and the fact that nothing was left behind. Re-run is safe.

### `seed-from-example`

A match triggers a substitution: gwm overwrites the offending file with the contents of `example_file` (still relative to the **main** checkout, since the worktree is fresh and unlikely to have its own example). Reported as `!` (warning), pipeline continues.

```
bootstrap report:
  ! guard no-aws-rds on .env
      pattern 'amazonaws\.com' matched on line 12
      → substituted from .env.example
```

Useful when `.env` is genuinely sensitive but you want the worktree to have **some** working config (e.g. local sqlite) — the substitution lands you in a known-safe baseline you can iterate from.

## regex syntax

Patterns use the [`regex` crate](https://docs.rs/regex) — Perl-ish, no look-around. Anchors:

- No anchor → matches anywhere in the file.
- `^…$` with the multi-line flag `(?m)` → matches per-line.

Common patterns:

```toml
deny_patterns = [
  "amazonaws\\.com",                # AWS endpoints
  "(?m)^DB_PASSWORD=(?!$|\"\"$)",   # any non-empty DB_PASSWORD line
  "BEGIN .* PRIVATE KEY",           # accidental SSH keys
  "sk_live_[A-Za-z0-9]{20,}",       # Stripe live secret keys
]
```

Backslashes must be doubled inside TOML strings. Use TOML's literal strings (`'...'`) for raw regex if you have many backslashes:

```toml
deny_patterns = ['amazonaws\.com', '\.rds\.']
```

## doctor coverage

`gwm doctor` check **#2** (`guard references resolve`) validates that every `[[bootstrap.copy]].guards = [...]` name points at an existing `[[bootstrap.guard]]`. Catches typos at config-time instead of waiting for the next `gwm create` to fail. See [Integrations → `gwm doctor`](/integrations/doctor).

## related

- [Bootstrap pipeline]/configuration/bootstrap — where guards sit in the execution order
- [`.gwm.toml` schema]/configuration/gwm-toml — full type reference