Skip to main content

Configuration System

This module describes the Morphir configuration system design, covering project configuration, workspace configuration, and the merge/resolution rules.

Overview

Morphir uses a unified configuration file (morphir.toml) that supports both single-project and multi-project (workspace) modes. The same file format handles:

  • Project mode: Single project with its own configuration
  • Workspace mode: Multiple projects with shared configuration

Configuration File

All configuration lives in morphir.toml (or alternative locations). There is no separate workspace configuration file.

my-workspace/
├── morphir.toml # Workspace-level config (has [workspace] section)
├── .config/
│ └── morphir/
│ └── config.toml # Workspace-level shared config (gitignored secrets, local overrides)
├── packages/
│ ├── core/
│ │ ├── morphir.toml # Project-level config
│ │ └── src/
│ └── domain/
│ ├── morphir.toml # Project-level config
│ └── src/

Mode Detection

The presence of specific sections determines the mode:

Section PresentModeBehavior
[project] onlyProjectSingle project configuration
[workspace]WorkspaceMulti-project with member discovery
BothWorkspace + Root ProjectWorkspace with the root also being a project

Module Reference

ModuleDescription
morphir.tomlConfiguration file structure and sections
Workspace ModeWorkspace-specific configuration and discovery
TasksTask definitions and pre/post hooks
Merge RulesConfiguration inheritance and merge behavior
EnvironmentEnvironment variables and runtime overrides

Key Sections

Core Configuration

[morphir]
version = "^4.0.0" # IR version constraint

[project]
name = "my-org/my-project"
version = "1.0.0"
source_directory = "src"
exposed_modules = ["Domain.User", "Domain.Order"]

# Frontend/language configuration
[frontend]
language = "elm" # Default: "elm", also "morphir-dsl", or extension-provided

Frontend Configuration

The [frontend] section specifies the input language and parser:

[frontend]
language = "elm" # Source language

# Language-specific options
[frontend.elm]
elm_version = "0.19"

[frontend.morphir-dsl]
strict_mode = true

Automatic Language Detection:

When language is not specified, Morphir infers it from file extensions:

ExtensionLanguage
.elmElm
.morphir, .mdslMorphir DSL
(Extension-defined)Per extension

Extension-Provided Frontends:

[extensions]
frontend-ocaml = { path = "./extensions/ocaml-frontend.wasm" }

[frontend]
language = "ocaml" # Now available via extension

[frontend.ocaml]
ocaml_version = "5.0"

Pattern-Based Language Selection:

For projects with multiple source languages:

[frontend]
language = "elm" # Default

[[frontend.rules]]
pattern = "src/legacy/**/*.morphir"
language = "morphir-dsl"

[[frontend.rules]]
pattern = "src/experimental/**/*.ml"
language = "ocaml"

Workspace Configuration

[workspace]
output_dir = ".morphir"
members = ["packages/*"] # Glob patterns for project discovery
exclude = ["packages/old-*"]
default_member = "packages/core"

Build & Codegen

[ir]
format_version = 4
strict_mode = false

[codegen]
targets = ["typescript", "scala"]
output_format = "pretty"

Tasks

Built-in tasks (build, test, check, codegen, pack, publish) work automatically. Users define custom tasks or hooks:

[tasks]
# Custom task
integration = "./scripts/integration-tests.sh"

# CI pipeline using built-in tasks
[tasks.ci]
description = "Run CI pipeline"
depends = ["check", "test", "build"]

# Pre/post hooks extend built-in tasks
[tasks."post:build"]
run = "prettier --write .morphir-dist/"

See Tasks for full documentation.

Configuration Locations

Configuration can be placed in multiple locations:

LocationScopeTypical Use
./morphir.tomlProject/WorkspacePrimary configuration (committed)
./.morphir/morphir.tomlProject/WorkspaceAlternative location
./.config/morphir/config.tomlWorkspaceLocal overrides, secrets (often gitignored)
~/.config/morphir/config.tomlUserUser-level defaults and preferences
/etc/morphir/config.tomlSystemSystem-wide defaults

Configuration Resolution

Configuration is resolved from multiple sources with the following precedence (highest first):

  1. Command-line flags: --config-key=value
  2. Environment variables: MORPHIR__SECTION__KEY
  3. Workspace local config: ./.config/morphir/config.toml
  4. Project/Workspace config: ./morphir.toml or ./.morphir/morphir.toml
  5. Parent configs: Walk up directory tree (for nested projects)
  6. User config: ~/.config/morphir/config.toml
  7. System config: /etc/morphir/config.toml

The .config/morphir/config.toml within a workspace is useful for:

  • Local developer overrides (gitignored)
  • Secrets and credentials
  • Machine-specific paths
  • CI/CD environment-specific settings

See Merge Rules for detailed merge semantics.

Workspace vs Project Config

AspectProject ConfigWorkspace Config
ScopeSingle packageMultiple packages
Filemorphir.toml in project dirmorphir.toml at workspace root
Key section[project][workspace]
DependenciesPer-projectCan be shared
Build outputPer-project .morphir-dist/Workspace .morphir/

Design Principles

  1. Single File Format: One morphir.toml format for all modes
  2. Explicit Over Implicit: Workspace mode requires explicit [workspace] section
  3. Inheritance: Child projects inherit from parent workspace config
  4. Override: More specific config overrides less specific
  5. Simple Tasks: Tasks are shell commands, not a DSL; pre/post hooks extend built-in commands
  6. Separation of Concerns: Committed config vs local overrides (.config/)