In Salesforce, the test environment lives in Setup, Custom Settings and org-level metadata. None of it is in source control, and none of it reaches your team automatically. Nimbus reads all of it from one properties file you commit.
Put a nimbus.properties file in the project root and commit it. Every developer on the team then runs with the same database settings, governor limit enforcement, org defaults, custom setting seeds and tracing preferences, with nothing to configure by hand.
If you have used application.properties in Spring Boot or Quarkus, the format is the same. The configuration lives in your repo instead of in an org.
# nimbus.properties - commit this to your repo
# Governor limits: catch violations before they reach the org
nimbus.governor.mode=warn
# Org environment defaults
nimbus.org.currency=EUR
nimbus.org.locale=de_DE
nimbus.org.timezone=Europe/Berlin
# Seed custom setting org defaults
nimbus.seed.org-default.TriggerSettings__c=IsEnabled__c=true
nimbus.seed.org-default.AppConfig__c=Endpoint__c=https://api.example.com,Retries__c=3
# Testing
nimbus.test.parallel=4
nimbus.test.timeout=30s
# Tracing (disabled by default, enable when debugging)
nimbus.trace.enabled=false
nimbus.trace.level=normalYour local machine, your CI pipeline and your staging environment need different settings. A profile is a set of overrides for one of those contexts, defined in the same file. There are no separate config files and no environment-specific branches.
Prefix any property with %profile. to create a profile-specific override. Activate a profile with NIMBUS_PROFILE=ci or --profile ci. Properties without a prefix apply everywhere. Profile-specific values override the defaults.
# Default: relaxed for local development
nimbus.governor.mode=warn
nimbus.trace.enabled=true
nimbus.trace.level=verbose
# CI: strict enforcement, no browser
%ci.nimbus.governor.mode=strict
%ci.nimbus.test.parallel=2
%ci.nimbus.trace.enabled=false
%ci.nimbus.devui.open-browser=false
# Staging: production-like limits
%staging.nimbus.governor.mode=strict
%staging.nimbus.test.timeout=120s# Activate a profile
NIMBUS_PROFILE=ci nimbus test
# Or via CLI flag
nimbus test --profile ciReference environment variables in your properties file with ${VAR} syntax. Add a default value with ${VAR:default}. This keeps secrets out of your committed config while still sharing the structure with your team.
# Use environment variables for secrets
nimbus.db.url=${DATABASE_URL}
nimbus.db.password=${DB_PASSWORD:localdev}
# CI can set these, local dev uses defaults
nimbus.org=${SF_ORG:default}Nimbus loads properties from three levels. Later levels override earlier ones, so an admin can set system-wide defaults and a project overrides what it needs.
/etc/nimbus/nimbus.propertiesCompany-wide defaults set by an admin. Lowest priority.~/.nimbus/nimbus.propertiesPersonal preferences: your timezone, your editor port, your trace level../nimbus.propertiesCommitted to git and shared with the team. Highest priority.Many Apex codebases read configuration from Custom Settings: feature flags, endpoint URLs, retry counts. In an org they are set through Setup. Locally you would need a @testSetup method in every test class to insert them.
With nimbus.seed.org-default, you define the org-default values once in the properties file. Every test sees them without a @testSetup method, and the values are the same on every machine. Read them the same way as on the platform: MySettings__c.getOrgDefaults().
# Seed org-default custom settings in nimbus.properties
nimbus.seed.org-default.TriggerSettings__c=IsEnabled__c=true,RunValidation__c=true
nimbus.seed.org-default.IntegrationConfig__c=Endpoint__c=https://api.example.com,ApiKey__c=test-key
nimbus.seed.org-default.FeatureFlags__c=EnableNewUI__c=false,EnableBetaFeatures__c=trueOrg defaults can also be passed on the CLI, for one-off runs or CI overrides that should not touch the properties file:
# Seed via CLI flag (repeatable for multiple objects)
nimbus test --org-default "TriggerSettings__c.IsEnabled__c=true"
nimbus test --org-default "AppConfig__c.Endpoint__c=https://api.example.com,Retries__c=3"Nimbus reads the project's metadata alongside the Apex. Permission Sets load from .permissionset-meta.xml files. Custom Metadata Types are discovered from .md-meta.xml files and can be queried with SOQL. Record Types are seeded from the project structure.
System.runAs() works locally. Set up a user with specific Permission Set assignments and test that your code respects object permissions, field-level security and SOQL WITH USER_MODE access checks, without an org.
Permission-dependent logic (does this profile see this field, does this user have create access) is testable on your machine, in milliseconds.
// Test permission-based logic locally
@isTest
static void testRestrictedAccess() {
// Create a user with specific permissions
User restrictedUser = new User(
ProfileId = restrictedProfileId,
Username = 'test@nimbus.dev'
);
System.runAs(restrictedUser) {
// Your code runs with this user's
// object and field permissions
try {
insert new Account(Name = 'Test');
System.assert(false, 'Should have failed');
} catch (DmlException e) {
// Permission enforced locally
}
}
}# Auto-seed RecordTypes from project metadata
nimbus.seed.record-types=true
# Set default RecordType per object for inserts
# without explicit RecordTypeId (mirrors profile defaults)
nimbus.default-record-type.Lead=Prospect_Record_Type
nimbus.default-record-type.Case=Support_Case
# Seed ListViews not in your repo metadata
# (standard objects have built-in views in Salesforce)
nimbus.seed.list-view.Lead.AllLeads=All Leads
nimbus.seed.list-view.Lead.MyLeads=My Leads
# Custom Metadata Types are auto-discovered
# from your force-app/.../customMetadata/ dir
# and queryable via SOQL in testsRun nimbus config init to write a documented nimbus.properties file with every available property, its description and example profiles. Uncomment what you need and commit the file.
# Generate a documented nimbus.properties file
nimbus config init
# See current effective configuration (with sources)
nimbus config show
# List all available properties
nimbus config propertiesAll 35 configuration properties, grouped by category.
Where Nimbus stores test data: embedded PostgreSQL, Docker, or an external instance.
| Property | Type | Default | Description |
|---|---|---|---|
nimbus.db.provider | string | embedded | Database provider: embedded, docker, or external |
nimbus.db.url | string | - | PostgreSQL connection string (overrides provider) |
nimbus.db.name | string | (auto) | Database name override |
nimbus.db.dir | string | .nimbus/db | Embedded Postgres data directory |
nimbus.db.pool.max-connections | int | 100 | Maximum database connections |
nimbus.db.pool.idle-timeout | duration | 1m | Connection idle timeout |
nimbus.db.lock-timeout | duration | 5s | Database lock timeout |
How tests execute: parallelism, timeouts, exclusions.
| Property | Type | Default | Description |
|---|---|---|---|
nimbus.test.parallel | int | (NumCPU) | Number of parallel test workers |
nimbus.test.timeout | duration | 60s | Timeout per test method |
nimbus.test.fallback-to-cli | bool | false | Fall back to Salesforce CLI for unsupported features |
nimbus.test.exclude | list | - | Exclude patterns (comma-separated) |
Execution traces: enable them, set the verbosity, choose the output location.
| Property | Type | Default | Description |
|---|---|---|---|
nimbus.trace.enabled | bool | false | Enable execution tracing |
nimbus.trace.level | string | normal | Trace verbosity: minimal, normal, verbose, debug, system |
nimbus.trace.output | string | .nimbus/traces | Directory for trace output files |
nimbus.trace.max-value-length | int | 1000 | Maximum value length in traces |
Salesforce governor limits enforced locally, so violations show up before the code reaches the org.
| Property | Type | Default | Description |
|---|---|---|---|
nimbus.governor.mode | string | warn | Enforcement mode: strict (fail), warn (log), off |
nimbus.governor.soql-queries | int | 100 | SOQL query limit per transaction |
nimbus.governor.dml-statements | int | 150 | DML statement limit per transaction |
nimbus.governor.heap-size | int | 12000000 | Heap size limit in bytes |
The simulated org environment: currency, locale, timezone, user identity and custom setting defaults.
| Property | Type | Default | Description |
|---|---|---|---|
nimbus.org.currency | string | USD | Default currency for UserInfo.getDefaultCurrency() |
nimbus.org.locale | string | en_US | Default locale for UserInfo.getLocale() |
nimbus.org.timezone | string | America/Los_Angeles | Default timezone |
nimbus.mock.user-id | string | 005000000000000AAA | Mock user ID for CreatedById / LastModifiedById |
nimbus.seed.record-types | bool | true | Auto-seed RecordTypes from project metadata |
nimbus.seed.org-default.<Object> | string | - | Seed custom setting org defaults (see examples below) |
nimbus.default-record-type.<Object> | string | - | Default RecordType DeveloperName for inserts without explicit RecordTypeId |
nimbus.seed.list-view.<Object>.<DevName> | string | - | Seed a ListView record (value is the label) |
General project settings: default org, caching, output verbosity.
| Property | Type | Default | Description |
|---|---|---|---|
nimbus.org | string | default | Default Salesforce org alias (for nimbus sync) |
nimbus.cache.dir | string | .nimbus/cache | AST cache directory |
nimbus.verbose | bool | false | Verbose CLI output |
The browser-based Dev UI and the background daemon.
| Property | Type | Default | Description |
|---|---|---|---|
nimbus.devui.port | int | 8080 | Dev UI server port |
nimbus.devui.open-browser | bool | true | Open browser automatically on nimbus dev |
nimbus.daemon.auto-start | bool | false | Auto-start daemon on test run for warm caches |
Run nimbus config init and commit the file. From then on the test environment is configured from the repo.