# How Worktrunk Handles Branch Naming Conventions to Prevent Errors

> Worktrunk automatically normalizes Git branch names with sanitize filters, preventing filesystem and database errors by stripping illegal characters before use in paths, containers, or scripts.

- Repository: [Maximilian Roos/worktrunk](https://github.com/max-sixty/worktrunk)
- Tags: how-to-guide
- Published: 2026-09-14

---

**Worktrunk prevents filesystem and database errors by automatically normalizing Git branch names through built-in `sanitize` and `sanitize_db` filters that strip illegal characters before using names in file paths, Docker containers, or hook scripts.**

Worktrunk is a Rust-based Git worktree management tool that treats branch names as structured data rather than raw strings. Because Git branch names can legally contain slashes, spaces, and other characters that are illegal in file paths or database identifiers, Worktrunk enforces strict branch naming conventions through automatic sanitization rules applied across all templating contexts.

## Built-in Jinja-like Sanitization Filters

Worktrunk ships with two template filters that are automatically applied to the `{{ branch }}` variable in its internal templating engine. These filters ensure that branch names are safe for their intended destinations.

### The `sanitize` Filter for Filesystem Safety

The **`sanitize`** filter makes branch names safe for **file-system paths**, including worktree directories and log files. It replaces forward slashes (`/`) and backslashes (`\`) with hyphens (`-`), while preserving other characters unchanged. This prevents directory traversal bugs and invalid path errors when Worktrunk creates directories or writes files.

### The `sanitize_db` Filter for Database Identifiers

The **`sanitize_db`** filter prepares branch names for use as **database identifiers**, such as Docker container names or PostgreSQL database names. This filter performs four transformations:

1. Converts the string to lowercase
2. Replaces any non-alphanumeric character with an underscore (`_`)
3. Prefixes the result with an underscore if it would start with a digit
4. Truncates to 48 characters and appends a short hash-suffix for uniqueness

This prevents naming collisions where two distinct branches might otherwise map to the same identifier.

## Core Implementation Files

The sanitization pipeline is implemented in two key source files within the `max-sixty/worktrunk` repository.

### src/path.rs

The core sanitization routine is defined in **[`src/path.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/path.rs)** as the `sanitize_for_filename` function. This function implements the slash-to-dash replacement logic used by the `sanitize` filter and is called directly when Worktrunk constructs internal log file paths.

### src/template.rs

During startup, Worktrunk registers the filters with the `minijinja` template engine in **[`src/template.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/template.rs)**. The registration code maps the filter names (`sanitize`, `sanitize_db`) to the Rust functions that perform the transformations, making them available in every Worktrunk template including [`config.toml`](https://github.com/max-sixty/worktrunk/blob/main/config.toml) and hook scripts.

## Contexts Where Sanitization Is Applied

Worktrunk applies these filters automatically across multiple contexts to prevent runtime errors.

**Worktree Path Templates** – The `worktree-path` configuration uses `{{ branch | sanitize }}` to create directories. For example, a branch named `feature/auth/login` becomes `.worktrees/feature-auth-login`. This is demonstrated in [`tests/integration_tests/config_show.rs`](https://github.com/max-sixty/worktrunk/blob/main/tests/integration_tests/config_show.rs) at lines 168-173.

**Hook Variables** – Hooks receive a sanitized `branch` variable when the script needs a safe filename, though the raw branch name remains available for logic operations. See [`tests/integration_tests/user_hooks.rs`](https://github.com/max-sixty/worktrunk/blob/main/tests/integration_tests/user_hooks.rs) at lines 3790-3840 for implementation details.

**Docker and Database Names** – Configuration templates for Docker containers use `{{ branch | sanitize_db }}` to generate valid container names. For a branch `123/feature-xyz`, the output resembles `_123_feature_xyz_ab12`, conforming to Docker's naming rules.

**Log File Paths** – When the logger writes to paths containing branch names, the branch component is passed through `sanitize_for_filename` to guarantee valid filenames, as shown in [`tests/integration_tests/config_state.rs`](https://github.com/max-sixty/worktrunk/blob/main/tests/integration_tests/config_state.rs) at lines 7-15.

**Symbolic Switch Arguments** – When a user runs `wt switch @` (referring to the current branch), Worktrunk resolves the symbolic reference first, then passes the resolved name through the sanitization pipeline before any hook executes, as implemented in [`tests/integration_tests/user_hooks.rs`](https://github.com/max-sixty/worktrunk/blob/main/tests/integration_tests/user_hooks.rs) at lines 3417-3424.

## Practical Configuration Examples

### Configuring Worktree Paths

```toml

# dev/config.example.toml

worktree-path = ".worktrees/{{ branch | sanitize }}"

```

When switching to a branch called `feature/auth/login`, Worktrunk creates the directory `.worktrees/feature-auth-login`.

### Using the Branch in a Hook

```sh

# .github/worktrunk/hooks/pre-start

#!/usr/bin/env sh

# Log the sanitized branch name for diagnostics

echo "Running on branch {{ branch | sanitize }}" >> "$WT_LOG/pre-start.log"

```

Running `wt switch feature/auth/login` writes a line containing `feature-auth-login` to the log.

### Database-Safe Names

```toml

# dev/docker-compose.yml (template)

services:
  db:
    container_name: "{{ repo }}-{{ branch | sanitize_db }}"

```

For a branch `123/feature-xyz`, the container name becomes something like `myrepo-_123_feature_xyz_ab12`.

## Summary

- Worktrunk uses **`sanitize`** and **`sanitize_db`** filters to normalize branch names for different contexts
- The **`sanitize_for_filename`** function in [`src/path.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/path.rs) handles filesystem safety by replacing slashes with hyphens
- Templates automatically apply these filters in `worktree-path` configurations, hook scripts, and Docker templates
- The **`sanitize_db`** filter prevents collisions and ensures valid identifiers by lowercasing, underscoring non-alphanumeric characters, and appending hash suffixes
- All sanitization is registered in **[`src/template.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/template.rs)** using the minijinja template engine

## Frequently Asked Questions

### What characters does Worktrunk remove from branch names?

For filesystem paths, Worktrunk replaces forward slashes (`/`) and backslashes (`\`) with hyphens using the `sanitize` filter. For database identifiers, the `sanitize_db` filter replaces any non-alphanumeric character with an underscore.

### How does Worktrunk handle branch names that start with numbers for database identifiers?

The `sanitize_db` filter automatically prefixes the sanitized string with an underscore (`_`) if the result would start with a digit. This ensures compliance with Docker and PostgreSQL naming rules that prohibit identifiers beginning with numbers.

### Where is the branch sanitization logic implemented in the Worktrunk source code?

The core logic resides in **[`src/path.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/path.rs)** within the `sanitize_for_filename` function, while the template filter registration occurs in **[`src/template.rs`](https://github.com/max-sixty/worktrunk/blob/main/src/template.rs)** using the minijinja template engine. Integration tests in [`tests/integration_tests/config_show.rs`](https://github.com/max-sixty/worktrunk/blob/main/tests/integration_tests/config_show.rs) and [`user_hooks.rs`](https://github.com/max-sixty/worktrunk/blob/main/user_hooks.rs) demonstrate the filters in action.

### Can I use raw branch names in Worktrunk hooks?

Yes, hooks receive the raw branch name via the `branch` variable for comparison logic and conditional operations. However, you should apply the `{{ branch | sanitize }}` filter when using the branch name in file paths, commands, or any context where filesystem-safe strings are required.