In Salesforce, your test environment is configured through Setup UI, Custom Settings, and org-level metadata - none of it in source control, none of it shared automatically with your team. Nimbus changes that with a single committable properties file.
Drop a nimbus.properties file in your project root, commit it to git, and every developer on your team gets the same test configuration - database settings, governor limit enforcement, org defaults, custom setting seeds, tracing preferences - without configuring anything manually.
If you've used application.properties in Spring Boot or Quarkus, this will feel familiar. If you haven't - this is what configuration looks like when it 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. Profiles let you define overrides for each context in the same file - no separate config files, no environment-specific branches, no "it works on my machine."
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}Properties are loaded from three levels. Later levels override earlier ones, so you can set sensible system-wide defaults and let projects override what they need.
/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. Shared with the team. Highest priority.Many Apex codebases rely on Custom Settings for configuration - feature flags, endpoint URLs, retry counts. In an org, these are set through Setup UI. Locally, you'd need@testSetup methods to insert them in every test class.
With nimbus.seed.org-default, you define org-default Custom Setting values once in your properties file. They're available in every test, automatically - no@testSetup boilerplate, no forgotten test data, no "this test only passes in my org because I have the setting configured." Access them the same way you would 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=trueYou can also pass org defaults via the CLI - useful for one-off runs or CI overrides without changing 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 doesn't just run your Apex - it understands your project's metadata. Permission Sets are loaded from your .permissionset-meta.xml files. Custom Metadata Types are auto-discovered from .md-meta.xml files and queryable via SOQL. Record Types are seeded automatically from your 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. No org required.
This means you can test permission-dependent logic - "does this profile see this field?", "does this user have create access?" - 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=Applicant_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 generate a documented nimbus.properties file with all available properties, descriptions, and example profiles. Uncomment what you need, commit to git, and your team is configured.
# 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.
Configure how Nimbus stores test data - embedded PostgreSQL, Docker, or connect to 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 |
Control 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) |
Configure execution traces - enable, set verbosity, choose 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 |
Enforce Salesforce governor limits locally - catch violations before they reach 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 |
Configure 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 |
Configure the browser-based Dev UI and 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 to get started. Commit the file. Never configure a test environment manually again.