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 Present | Mode | Behavior |
|---|---|---|
[project] only | Project | Single project configuration |
[workspace] | Workspace | Multi-project with member discovery |
| Both | Workspace + Root Project | Workspace with the root also being a project |
Module Reference
| Module | Description |
|---|---|
| morphir.toml | Configuration file structure and sections |
| Workspace Mode | Workspace-specific configuration and discovery |
| Tasks | Task definitions and pre/post hooks |
| Merge Rules | Configuration inheritance and merge behavior |
| Environment | Environment 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:
| Extension | Language |
|---|---|
.elm | Elm |
.morphir, .mdsl | Morphir 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:
| Location | Scope | Typical Use |
|---|---|---|
./morphir.toml | Project/Workspace | Primary configuration (committed) |
./.morphir/morphir.toml | Project/Workspace | Alternative location |
./.config/morphir/config.toml | Workspace | Local overrides, secrets (often gitignored) |
~/.config/morphir/config.toml | User | User-level defaults and preferences |
/etc/morphir/config.toml | System | System-wide defaults |
Configuration Resolution
Configuration is resolved from multiple sources with the following precedence (highest first):
- Command-line flags:
--config-key=value - Environment variables:
MORPHIR__SECTION__KEY - Workspace local config:
./.config/morphir/config.toml - Project/Workspace config:
./morphir.tomlor./.morphir/morphir.toml - Parent configs: Walk up directory tree (for nested projects)
- User config:
~/.config/morphir/config.toml - 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
| Aspect | Project Config | Workspace Config |
|---|---|---|
| Scope | Single package | Multiple packages |
| File | morphir.toml in project dir | morphir.toml at workspace root |
| Key section | [project] | [workspace] |
| Dependencies | Per-project | Can be shared |
| Build output | Per-project .morphir-dist/ | Workspace .morphir/ |
Design Principles
- Single File Format: One
morphir.tomlformat for all modes - Explicit Over Implicit: Workspace mode requires explicit
[workspace]section - Inheritance: Child projects inherit from parent workspace config
- Override: More specific config overrides less specific
- Simple Tasks: Tasks are shell commands, not a DSL; pre/post hooks extend built-in commands
- Separation of Concerns: Committed config vs local overrides (
.config/)
Related Documents
- morphir.toml Specification - Formal spec
- Merge Rules - Merge behavior spec
- Workspace Operations - Runtime workspace management