Skip to main content

Configuration

datamitsu uses JavaScript configuration files to define your tools, runtimes, and project settings. The configuration system supports layered composition, remote inheritance, and dynamic generation through a full JavaScript runtime.

Configuration Files

datamitsu automatically discovers configuration at your git repository root. It looks for one of these files:

  • datamitsu.config.js
  • datamitsu.config.mjs
  • datamitsu.config.ts

If more than one exists, datamitsu returns an error. You can disable auto-discovery with --no-auto-config.

Every configuration file must export two functions:

  • getMinVersion() — Returns the minimum datamitsu version required (semver string). For stable builds, the loader fails with upgrade instructions if the current version is too old. Unstable builds (0.0.0-unstable.<date>.<sha>, produced from non-tagged commits) skip the check and emit an advisory warning instead — users on those builds have already opted into a non-released binary.
  • getConfig(config) — Receives the accumulated configuration from previous layers and returns a new config.

The /// <reference path=".datamitsu/datamitsu.config.d.ts" /> directive at the top of config files enables IDE autocomplete and type checking. This file is automatically generated in the .datamitsu/ directory when you run datamitsu init and contains TypeScript type definitions for the configuration API.

A minimal configuration file:

/// <reference path=".datamitsu/datamitsu.config.d.ts" />

function getConfig(config) {
return {
...config,
apps: {
...config.apps,
// your app definitions
},
};
}

globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "0.0.1";

If getMinVersion() is missing, the config fails to load with: "config must export getMinVersion() function returning semver string".

Config Loading Order

Configuration is loaded in layers, where each layer receives the result of the previous one:

default (embedded config.js)
↓ [getRemoteConfigs() resolved]
--before-config flags
↓ [getRemoteConfigs() resolved]
declared before-configs (auto config's getBeforeConfigs(), only if no --before-config flag)
↓ [getRemoteConfigs() resolved]
auto (datamitsu.config.js at git root)
↓ [getRemoteConfigs() resolved]
--config flags

final Config

Each layer can modify, extend, or override the configuration from previous layers.

Default Configuration

datamitsu ships with a built-in default configuration that provides common tools and sensible defaults. This is always the starting point.

Before-Config (--before-config)

Use --before-config to load configuration files before auto-discovery. This is intended for wrapper packages and shared libraries that provide base configurations:

datamitsu check --before-config ./node_modules/@myorg/datamitsu-config/base.js

Declared Before-Configs (getBeforeConfigs())

getBeforeConfigs() is the config-declared equivalent of the --before-config flag. Export it from your auto-discovered git-root config to load local config files as under-layers — without passing --before-config on the command line:

/// <reference path=".datamitsu/datamitsu.config.d.ts" />

function getBeforeConfigs() {
return [{ path: "./node_modules/@myorg/datamitsu-config/datamitsu.config.js" }];
}
globalThis.getBeforeConfigs = getBeforeConfigs;

function getConfig(config) {
// config already includes the declared before-config's changes
return { ...config };
}
globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "0.0.1";

The declared paths are inserted into the loading order before the auto config, giving them exact parity with --before-config (init-layer merging, getMinVersion() checks, remote-config resolution).

Key rules:

  • Why use it: a wrapper's bin/datamitsu shim injects --before-config only when datamitsu is invoked through it. A globally installed datamitsu run in the same repo never gets that flag and so skips the shared config. Declaring getBeforeConfigs() in your git-root config makes the global binary reproduce the wrapper's behaviour automatically — see Maintaining Wrapper Packages.
  • Path resolution: relative paths resolve against the directory of the git-root config file; absolute paths are used as-is. Duplicate paths are deduplicated, declared order is preserved, and a missing file is an error.
  • No hash required: local paths are in the same trust domain as the root config — they are not network downloads, so the mandatory-hash policy (which applies to getRemoteConfigs()) does not apply.
  • Root-only scope: getBeforeConfigs() is honoured only in the auto-discovered git-root config. A declaration in any other layer (default, --before-config, a remote config, --config, or a declared before-config itself) is ignored — there is no chaining.
  • Precedence: if --before-config is passed on the CLI, getBeforeConfigs() is not evaluated at all. The flag wins, which avoids double-loading the shared config when the wrapper is used.

Auto-Discovery

datamitsu automatically finds and loads your project's configuration file at the git root. Disable this with --no-auto-config when you want full control over which configs are loaded.

Config Overrides (--config)

Use --config to load additional configuration files after auto-discovery. This is useful for CI-specific overrides or testing:

datamitsu check --config ./ci-config.js

Remote Configs

Any configuration file can export a getRemoteConfigs() function to inherit from remote configurations:

/// <reference path=".datamitsu/datamitsu.config.d.ts" />

function getRemoteConfigs() {
return [
{
url: "https://example.com/shared-datamitsu-config.js",
hash: "a1b2c3d4e5f6...", // SHA-256 hash (required)
},
];
}
globalThis.getRemoteConfigs = getRemoteConfigs;

Remote configs are resolved depth-first before the current config's getConfig() runs. This creates an inheritance chain where your local config can build on top of shared organization-wide settings.

Key requirements:

  • Every remote config must have a SHA-256 hash for security verification
  • Remote configs are cached locally; cache validity is determined by hash match (no TTL)
  • Circular dependencies are detected and produce an error
  • HTTPS-to-HTTP redirects are rejected for security

Wrapper Package Pattern

Remote configs enable a wrapper package pattern for sharing configuration across teams:

// @myorg/datamitsu-config/index.js
function getRemoteConfigs() {
return [
{
url: "https://config.myorg.com/datamitsu/base.js",
hash: "abc123...",
},
];
}
globalThis.getRemoteConfigs = getRemoteConfigs;

function getConfig(config) {
return {
...config,
// organization-specific overrides
};
}

globalThis.getConfig = getConfig;
globalThis.getMinVersion = () => "1.0.0";

Teams use this via --before-config:

datamitsu check --before-config ./node_modules/@myorg/datamitsu-config/index.js

Ignore Rules

Ignore rules can be defined both in .datamitsuignore files and in the configuration:

/// <reference path=".datamitsu/datamitsu.config.d.ts" />

function getConfig(config) {
return {
...config,
ignoreRules: [
"*.generated.ts: eslint, prettier",
"vendor/**/*: *",
"!vendor/important.go: golangci-lint",
],
};
}
globalThis.getConfig = getConfig;

Config-defined ignore rules use append semantics across config layers -- previous rules are preserved and new rules are added.

See the Ignore Rules reference for full syntax documentation.

JavaScript Runtime

Configuration files run in a JavaScript VM (goja) with access to several built-in APIs:

  • Format utilities: YAML.parse()/YAML.stringify(), TOML.parse()/TOML.stringify(), INI.parse()/INI.stringify() for parsing and generating config file content
  • Path utilities: tools.Path.join(), tools.Path.abs(), tools.Path.rel(), tools.Path.forImport()
  • Config links: tools.Config.linkPath() for computing paths to .datamitsu/ symlinks
  • Ignore utilities: tools.Ignore.parse(), tools.Ignore.stringify() for working with ignore patterns
  • Facts: facts() returns platform and environment information (os, arch, isInGitRepo, isMonorepo, env)
  • Console: console.log(), console.warn(), console.error() for debugging

See the Configuration API reference for complete API documentation.

The evaluated result is cached on disk per set of inputs, so an unchanged config chain is not re-evaluated on the next command (see the config-evaluation cache). A config that reads the clock (Date.now(), new Date() with no arguments), calls Math.random(), or writes to console.* still evaluates normally — it simply never gets a cache entry, because a cache hit runs no JavaScript and could not reproduce the value or the output. Dates built from explicit arguments (new Date(2020, 0, 1)) are pure and cost nothing.

Environment Variables

VariableDescriptionDefault
DATAMITSU_CONCURRENCYConcurrent downloads during init3
DATAMITSU_MAX_PARALLEL_WORKERSMax parallel tool workersmax(4, floor(NumCPU * 0.75)), capped at 16
DATAMITSU_UNIT_CACHE_TTLMinutes a project-level verdict is trusted1440 (24h)
DATAMITSU_LSP_FORMAT_WIDEN_TOEditor format-on-save wideningunit
DATAMITSU_CONFIG_CACHEServe the evaluated config chain from disk1 (0/false/off/no disables)
DATAMITSU_NO_SPONSORSuppress sponsor messages-
NO_COLORDisable color output-
FORCE_COLORForce color output-