mcpField
B
boxlang-configuration

boxlang-configuration

github.com/ortus-boxlangDevelopment044 installsUpdated 1w ago
Repository

About boxlang-configuration

A configuration guide for BoxLang developers, covering runtime settings, file locations, environment overrides, and services such as datasources, caches, and watchers.

Key features

  1. 01Config file locations and overrides
  2. 02Environment and path variable substitution
  3. 03Datasource, cache, and executor settings
  4. 04Module, logging, and security configuration
  5. 05Watcher and runtime settings

Use cases

  1. 01Adjust BoxLang settings across runtime environments
  2. 02Set database connection values through environment variables
  3. 03Configure modules, logs, and file monitoring
  4. 04Review global and application-level runtime settings

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/ortus-boxlang/skills --skill boxlang-configuration

After installing, type/boxlang-configurationin Claude Code to confirm it loaded.

Details

From the project README

BoxLang Configuration

BoxLang is the AI-native software productivity platform for building, modernizing and running applications, with developers and AI agents working together.

Overview

BoxLang's runtime is configured through boxlang.json. The file is auto-created in the BoxLang home directory on first startup. All settings can be overridden via environment variables or Java system properties without modifying the file.

When configuration questions involve app-specific behavior in Application.bx (this.name, lifecycle callbacks, per-app schedulers/watchers, nested app isolation), pair this with the application-descriptor skill.


Config File Locations

RuntimeDefault Location
OS / CLI / MiniServer~/.boxlang/config/boxlang.json
CLI project override (v1.18+)./.boxlang.json in the current working directory, used when BOXLANG_CONFIG / --bx-config are not set
AWS Lambda{lambdaRoot}/boxlang.json
Google Cloud Functions{gcfRoot}/boxlang.json
CommandBox~/.commandbox/servers/{home}/WEB-INF/boxlang/config/boxlang.json

Override the home directory at startup:

boxlang --home /path/to/custom-home

Environment Variable Overrides

Any setting can be overridden via environment variable or JVM property using the BOXLANG_ prefix (snake_case) or boxlang. prefix (dot-notation):

# Enable debug mode
BOXLANG_DEBUGMODE=true

# Set log level for runtime logger
boxlang.logging.loggers.runtime.level=TRACE

# Set as JVM argument
java -Dboxlang.debugMode=true -jar boxlang.jar

JSON values are supported for complex overrides:

BOXLANG_DATASOURCES='{"mainDB":{"driver":"postgresql","host":"db.example.com"}}'

Environment Variable Substitution

Use ${env.VAR:default} inside boxlang.json to reference env vars:

{
    "datasources": {
        "mainDB": {
            "driver":   "postgresql",
            "host":     "${env.DB_HOST:localhost}",
            "port":     "${env.DB_PORT:5432}",
            "database": "${env.DB_NAME:myapp}",
            "username": "${env.DB_USER:app}",
            "password": "${env.DB_PASSWORD}"
        }
    }
}

Built-in path substitution variables:

VariableResolves to
${boxlang-home}BoxLang home directory
${user-home}OS user home directory
${user-dir}Current working directory
${java-temp}Java temp directory

Core Directives

{
    // Compiled class output directory
    "classGenerationDirectory": "${boxlang-home}/classes",

    // Compiler backend: "asm" (default, best performance) or "java"
    "compiler": "asm",

    // Store compiled classes on disk (recommended: true for production)
    "storeClassFilesOnDisk": true,

    // Never re-check class files (recommended: true for production)
    "trustedCache": false,

    // Cache class resolver lookups (recommended: true)
    "classResolverCache": true,

    // Clear class files on startup (use only for debugging)
    "clearClassFilesOnStartup": false,

    // Global class paths (.bx file discovery)
    "classPaths": [
        "${boxlang-home}/global/classes"
    ],

    // Custom component directories
    "customComponentsDirectory": [
        "${boxlang-home}/global/components"
    ],

    // Default datasource name
    "defaultDatasource": "",

    // Max completed threads tracked per request
    "maxTrackedCompletedThreads": 1000,

    // Enable debug output in responses
    "debugMode": false
}

Datasources

{
    "datasources": {
        "mainDB": {
            "driver":   "postgresql",
            "host":     "${env.DB_HOST:localhost}",
            "port":     5432,
            "database": "myapp",
            "username": "${env.DB_USER:app}",
            "password": "${env.DB_PASSWORD}"
        },
        "legacyMySQL": {
            "driver":   "mysql",
            "host":     "db2.internal",
            "port":     3306,
            "database": "legacy",
            "username": "${env.MYSQL_USER}",
            "password": "${env.MYSQL_PASS}",
            // Connection pool settings
            "connectionTimeout":   30,
            "maximumPoolSize":     10,
            "minimumIdle":         2
        }
    }
}

Supported drivers: postgresql, mysql, mssql, oracle, derby, h2, sqlite.


Caches

{
    "caches": {
        // Default cache (used when no cache name specified)
        "default": {
            "provider": "BoxCacheProvider",
            "properties": {
                "maxObjects":       1000,
                "defaultTimeout":   60,
                "defaultLastAccessTimeout": 0,
                "objectStore":      "ConcurrentStore"
            }
        },
        // Named cache for templates
        "templates": {
            "provider": "BoxCacheProvider",
            "properties": {
                "maxObjects": 500,
                "defaultTimeout": 120
            }
        }
    }
}

Executors

{
    "executors": {
        // Default executor for runAsync() — virtual threads
        "boxlang-tasks": {
            "type": "virtual",
            "coreThreads": 20
        },
        // CPU-bound work pool
        "cpu-work": {
            "type": "fixed",
            "coreThreads": 8
        },
        // Elastic pool for bursty I/O
        "io-tasks": {
            "type": "cached"
        },
        // Scheduler pool
        "scheduler": {
            "type": "scheduled",
            "coreThreads": 5
        }
    }
}

Executor types: virtual (default, Project Loom), fixed, cached, scheduled, work_stealing.


Logging

{
    "logging": {
        "logsDirectory": "${boxlang-home}/logs",
        "level": "WARN",   // Global default: TRACE, DEBUG, INFO, WARN, ERROR
        "loggers": {
            "runtime":    { "level": "INFO" },
            "scheduler":  { "level": "INFO", "async": true },
            "datasource": { "level": "WARN" },
            "cache":      { "level": "WARN" },
            "modules":    { "level": "INFO" }
        }
    }
}

Security

{
    "security": {
        // Regex patterns for blocked Java class imports
        "disallowedImports": [],
        // Blocked BIF names
        "disallowedBifs": [],
        // Blocked component names
        "disallowedComponents": [],
        // Whether Java system props/env are in server.system scope
        "populateServerSystemScope": true,
        // Explicit upload extension whitelist (overrides disallowed list)
        "allowedFileOperationExtensions": [],
        // Blocked file upload/move extensions
        "disallowedFileOperationExtensions": []
    }
}

Modules

Configure modules loaded at startup and module-specific settings:

{
    "modules": {
        // Modules to load on startup (in addition to auto-discovered modules)
        "load": [ "bx-compat-cfml", "bx-orm" ],
        // Modules to skip loading even if present
        "exclude": [],
        // Per-module settings
        "settings": {
            "bx-orm": {
                "autoManageSession": true,
                "dialect":           "PostgreSQLDialect"
            }
        }
    }
}

Scheduler

{
    "scheduler": {
        // Default task timeout (0 = no timeout)
        "defaultTimeout": 0,
        // How long to wait for scheduled tasks to complete on shutdown
        "shutdownTimeout": 30,
        // Executor to use for scheduled tasks
        "executor": "scheduler"
    }
}

Watcher

Configure the built-in WatcherService for filesystem monitoring. Watchers react to file/directory changes and can trigger hot-reload, asset builds, or custom automation.

{
    "watcher": {
        // Recurse into subdirectories by default
        "recursive": true,
        // Hold events until no new event arrives within this window (ms); 0 = off
        "debounce": 300,
        // Emit at most one event per window and drop the rest (ms); 0 = off
        "throttle": 0,
        // Suppress noisy intermediate events from atomic save patterns (temp + rename)
        "atomicWrites": true,
        // Startup delay before watchers begin processing events (ms)
        "delay": 0,
        // Auto-stop watcher after this many consecutive listener errors (0 = disabled)
        "errorThreshold": 10,
        // Named watcher definitions auto-started at runtime startup
        "definitions": {
            "hot-reload": {
                "paths":    "${user-dir}/src",
                "listener": "app.listeners.HotReloadListener"
            },
            "assets": {
                "paths":     [ "${user-dir}/resources/css", "${user-dir}/resources/js" ],
                "recursive": false,
                "throttle":  500,
                "listener":  "app.listeners.AssetPipelineListener"
            }
        }
    }
}
Watcher Definition Properties
PropertyRequiredDescription
pathsYesDirectory path or array of paths to watch
listenerYesBoxLang class path with listener behavior
recursiveNoOverride global recursive setting
debounceNoPer-watcher debounce override (ms)
throttleNoPer-watcher throttle override (ms)
atomicWritesNoPer-watcher atomic write filtering override
delayNoPer-watcher startup delay override (ms)
errorThresholdNoPer-watcher error threshold override

For closures and struct-based listeners, create watchers programmatically with watcherNew() at runtime instead of in boxlang.json.

Runtime Watcher BIFs

watcherNew(), watcherStart(), watcherStop(), watcherRestart(), watcherList(), watcherGet(), watcherExists(), watcherShutdown(), watcherStopAll(), watcherShutdownAll()


Runtime Settings

User-defined global named settings. BoxLang does not interpret them. Values can be any type (strings, numbers, booleans, structs, arrays) and keys are unique.

{
    "runtimeSettings": {
        "apiUrl":    "${env.API_URL:http://localhost}",
        "stripeKey": "bxsecret:AbC123...",
        "features":  { "beta": true, "regions": [ "us", "eu" ] }
    }
}
  • ${env.VAR}, ${env.VAR:default}, the path variables and bxsecret: values resolve at any depth, including inside arrays. Interpolated values are strings. An unresolved placeholder with no default stays literal.
  • Read with the getRuntimeSetting( key, default ) BIF: dotted paths (features.beta), 1-based array indexes (features.regions.1), no args returns the whole merged struct, a missing key without a default throws.
  • Values are deeply read-only.
  • this.runtimeSettings in Application.bx (or bx:application runtimeSettings={...}) deep merges over the global struct, app wins by key. Arrays and scalars are replaced, not merged.
  • Global values resolve once at runtime config load. The Application.bx layer re-resolves ${...} and bxsecret: on every request when the descriptor is re-read, then is cached for that request. Only runtimeSettings is ${...} interpolated at the app layer.
  • This is different from getSystemSetting(), which reads Java system properties and environment variables.

Experimental

Feature flags for in-progress BoxLang capabilities. These settings may change or be removed.

{
    "experimental": {
        // Compiler backend: "asm" (default, direct bytecode) or "java" (transpile to Java first)
        "compiler": "asm",
        // Capture AST JSON to /grapher/data on each parse (for tooling/debugging only)
        "ASTCapture": false
    }
}
FlagDefaultDescription
compiler"asm""asm" compiles directly to bytecode (production default); "java" transpiles to Java source first
ASTCapturefalseWrites AST JSON to /grapher/data on every parse — for tooling and debugging only, never production

Application-Level Configuration (Application.bx)

Application-level settings override the runtime config for a specific app:

class {
    // Application identity
    this.name             = "MyApp"
    this.sessionManagement = true
    this.sessionTimeout   = createTimeSpan( 0, 2, 0, 0 )

    // Datasource
    this.datasource = "mainDB"

    // Per-application datasource definition
    this.datasources = {
        localDB: {
            driver:   "h2",
            database: expandPath( "/db/local.h2" )
        }
    }

    // Java library paths
    this.javaSettings = {
        loadPaths: [ expandPath( "/lib/" ) ]
    }

    // Cache mappings
    this.caches = {
        objects: { provider: "BoxCacheProvider" }
    }

    // Directory mappings
    this.mappings = {
        "/models":   expandPath( "/app/models/" ),
        "/services": expandPath( "/app/services/" )
    }
}

Production Configuration Checklist

  • trustedCache: true — no disk checks on every request
  • classResolverCache: true — cached class resolution
  • debugMode: false — no debug output to responses
  • logging.level: "WARN" — suppress verbose logs
  • Secrets via ${env.VAR} — never hardcoded in boxlang.json
  • classGenerationDirectory on a fast disk (SSD/tmpfs)
  • Connection pool sizes tuned for expected concurrency
  • security.populateServerSystemScope: false if system env not needed

Comments

Markdown supported