> For the complete documentation index, see [llms.txt](https://docs.flxbl.io/flxbl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flxbl.io/flxbl/sfp/development/string-replacements.md).

# String Replacements

String replacements provide a mechanism to manage environment-specific values in your Salesforce code without modifying source files. This feature automatically replaces placeholders with appropriate values during build, install, and push operations, and converts values back to placeholders during pull operations.

String replacements complement the existing [aliasfy packages](/flxbl/sfp/building-artifacts/configuring-installation-behaviour-of-a-package/aliasfy-packages.md) feature. While aliasfy packages handle structural metadata differences by deploying different files per environment, string replacements handle configuration value differences within the same files, reducing duplication and maintenance overhead.

{% hint style="warning" %}
Replacements are supported for **source packages only**. A `replacements.yml` in an unlocked, org-dependent unlocked, or data package fails the build — remove the file or change the package type to `source`.
{% endhint %}

### How It Works

String replacements work across multiple sfp commands:

**Build Operations**: During `sfp build`, replacement configurations are analyzed and embedded in the artifact for later use during installation.

**Install Operations**: During `sfp install`, placeholders are replaced with environment-specific values based on the target org:

```
Artifact (%%API_URL%%) → Install → Target Org (https://api.example.com)
```

**Push Operations**: During `sfp push`, placeholders in your source files are replaced with environment-specific values before deployment:

```
Source File (%%API_URL%%) → Push → Target Org (https://api.example.com)
```

**Pull Operations**: During `sfp pull`, environment-specific values are converted back to placeholders:

```
Target Org (https://api.example.com) → Pull → Source File (%%API_URL%%)
```

### Configuration

Replacements are configured in a `replacements.yml` file within each package's `preDeploy` directory:

```
src/
  your-package/
    preDeploy/
      replacements.yml
    main/
      default/
        classes/
```

Example configuration:

```yaml
replacements:
  - name: "API Endpoint"
    pattern: "%%API_ENDPOINT%%"
    glob: "**/*.cls"
    environments:
      default: "https://api-sandbox.example.com"
      dev: "https://api-dev.example.com"
      staging: "https://api-staging.example.com"
      prod: "https://api.example.com"

  - name: "Support Email"
    pattern: "%%SUPPORT_EMAIL%%"
    glob: "**/*.cls"
    environments:
      default: "support-sandbox@example.com"
      dev: "support-dev@example.com"
      prod: "support@example.com"
```

The properties accepted by the configuration file are:

| Field                  | Required | Description                                                             |
| ---------------------- | -------- | ----------------------------------------------------------------------- |
| `name`                 | Yes      | Human-readable name for the replacement                                 |
| `pattern`              | Yes      | The placeholder pattern to replace (e.g., `%%API_URL%%`)                |
| `glob`                 | Yes      | File pattern for matching files (e.g., `**/*.cls` for all Apex classes) |
| `environments`         | Yes      | Map of environment aliases to replacement values                        |
| `environments.default` | No       | Default value used for sandbox/scratch orgs (recommended)               |
| `description`          | No       | Longer description of what the replacement is for                       |
| `isRegex`              | No       | Whether the pattern is a regular expression (default: false)            |

A replacement value can reference a project variable or secret instead of carrying the value in the file:

```yaml
replacements:
  - name: "API Endpoint"
    pattern: "%%API_ENDPOINT%%"
    glob: "**/*.cls"
    environments:
      default: "${{ vars.API_ENDPOINT }}"
      prod: "${{ secrets.PROD_API_ENDPOINT }}"
```

Variables and secrets are resolved at deployment from the values configured for the project.

### Example Usage

#### API Configuration Example

Source file with placeholders:

```java
public class APIService {
    private static final String ENDPOINT = '%%API_ENDPOINT%%';
    private static final String API_KEY = '%%API_KEY%%';
}
```

After pushing to a dev org, the placeholders are replaced:

```java
public class APIService {
    private static final String ENDPOINT = 'https://api-dev.example.com';
    private static final String API_KEY = 'dev-key-12345';
}
```

### Pattern Detection

During pull operations, sfp automatically detects potential patterns that could be converted to replacements:

* **URLs**: Detects HTTP/HTTPS URLs
* **Email Addresses**: Identifies email patterns

When patterns are detected, sfp provides suggestions:

```
⚠️  Potential replacements detected:

  📄 src/package/main/default/classes/APIService.cls:
     • URL detected: 'https://new-api.example.com/v2'
       New URL pattern detected. Consider adding to replacements.yml

  💡 To include these values in future replacements, update your replacements.yml file.
```

### Environment Resolution

Replacements are resolved based on the target org:

* **Exact Alias Match**: First checks for an exact match with the org alias
* **Sandbox Default**: For sandbox and scratch orgs with no alias match, uses the `default` value. Where neither is present, the replacement is skipped with a warning
* **Production Requirement**: `default` is not applied to production orgs. Installing into a production org with no alias match fails

### Org Alias Mapping

The org alias is determined from your Salesforce CLI authentication:

```bash
# Check your org aliases
sf org list

# Push with specific org alias
sfp push -o dev-sandbox -p your-package
```

### Command Support

String replacements are supported across the following sfp commands:

| Command        | Description                                                                    |
| -------------- | ------------------------------------------------------------------------------ |
| `sfp build`    | Reads the configuration and embeds it in the artifact; does not itself replace |
| `sfp install`  | Applies replacements during artifact installation                              |
| `sfp push`     | Applies forward replacements during source push                                |
| `sfp pull`     | Applies reverse replacements during source pull                                |
| `sfp validate` | Applies replacements as part of the deployment it performs                     |

### Command Line Options

#### Disable Replacements

`--no-replacements` is available on `sfp push`:

```bash
sfp push -p your-package -o dev --no-replacements
```

{% hint style="info" %}
`sfp install` has no `--no-replacements` flag, and the flag on `sfp pull` currently has no effect — reverse replacements are always applied on pull.
{% endhint %}

#### Override Replacements

```bash
# Use override file during install
sfp install --targetorg dev --artifactdir artifacts --replacementsoverride custom-replacements.yml

# Use override file during push
sfp push -p your-package -o dev --replacementsoverride custom-replacements.yml
```

{% hint style="info" %}
`--replacementsoverride` is honoured by `sfp install` and `sfp push`. The flag exists on `sfp pull` but currently has no effect.
{% endhint %}

### JSON Output

Both push and pull commands support JSON output with detailed replacement information:

```bash
# Get JSON output with replacement details
sfp push -p your-package -o dev --json
sfp pull -p your-package -o dev --json
```

### JSON Output Structure

```json
{
  "hasError": false,
  "replacements": {
    "success": true,
    "packageName": "your-package",
    "filesModified": [
      {
        "path": "main/default/classes/APIService.cls",
        "replacements": [
          {
            "pattern": "%%API_ENDPOINT%%",
            "value": "https://api-dev.example.com",
            "count": 1
          }
        ],
        "totalCount": 1
      }
    ],
    "totalFiles": 1,
    "totalReplacements": 1,
    "errors": [],
    "orgAlias": "dev"
  }
}
```

### Troubleshooting

#### Replacements Not Applied

* **Check File Location**: Ensure `replacements.yml` is in `preDeploy` directory
* **Verify Glob Pattern**: Test glob pattern matches your files
* **Check Org Alias**: Verify the org alias matches your configuration
* **Review Logs**: Check debug logs for replacement processing

#### Pattern Not Found

* **Case Sensitivity**: Patterns are case-sensitive
* **Special Characters**: Escape special regex characters if needed
* **File Encoding**: Ensure files are UTF-8 encoded

#### Wrong Value Applied

* **Org Detection**: Verify org alias with `sf org list`
* **Environment Priority**: Check resolution order (exact match → default)
* **Override Files**: Check if override file is being used

### Limitations

* Replacements are text-based and work with any text file format
* Binary files are not supported
* Large files may impact performance
* Regex patterns should be used carefully to avoid unintended matches

### Related Documentation

* [String Replacements Configuration](/flxbl/sfp/building-artifacts/configuring-installation-behaviour-of-a-package/string-replacements.md) - Configure string replacements in packages
* [String Replacements During Install](/flxbl/sfp/installing-an-artifact/string-replacements-during-install.md) - How replacements work during installation
* [`sfp push`](/flxbl/sfp/development/push-changes-to-your-org.md) - Deploy changes with replacements
* [`sfp pull`](/flxbl/sfp/development/pull-changes-from-your-org.md) - Retrieve changes with reverse replacements


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.flxbl.io/flxbl/sfp/development/string-replacements.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
