Workspace Mode Configuration
This document describes workspace-specific configuration in morphir.toml.
Overview
A workspace is a collection of related Morphir projects managed together. Workspace mode is activated by including a [workspace] section in the configuration file.
Configuration File Locations
The configuration file can be placed in any of these equivalent locations:
| Location | Notes |
|---|---|
morphir.toml | Root level, most visible |
.morphir/config.toml | Hidden directory variant |
.morphir/morphir.toml | Hidden directory variant |
.config/morphir/config.toml | XDG-style location |
All locations use the same format and are functionally equivalent. The CLI searches in this order and uses the first file found.
Enabling Workspace Mode
# morphir.toml (or any equivalent location)
[workspace]
members = ["packages/*"]
The presence of [workspace] section triggers workspace mode, enabling:
- Multi-project discovery and management
- Shared dependency resolution
- Coordinated builds
- Workspace-wide configuration inheritance
Workspace Section
[workspace]
[workspace]
# Workspace root directory (empty = directory containing this file)
root = ""
# Output directory for workspace-level artifacts
output_dir = ".morphir"
# Glob patterns for discovering member projects
members = [
"packages/*",
"libs/*",
"apps/*"
]
# Patterns to exclude from discovery
exclude = [
"packages/deprecated-*",
"packages/experimental/*"
]
# Default member when no project is specified
default_member = "packages/core"
Field Reference
| Field | Type | Default | Description |
|---|---|---|---|
root | string | "" | Workspace root directory. Empty means the directory containing the config file. |
output_dir | string | ".morphir" | Output directory for generated artifacts, relative to workspace root. |
members | string[] | [] | Glob patterns for discovering workspace member projects. Each matching directory with a morphir.toml becomes a member. |
exclude | string[] | [] | Glob patterns excluded from member discovery. |
default_member | string | "" | Default member path when none is specified in commands. |
Project Discovery
Projects are discovered by scanning directories matching members patterns:
workspace/
├── morphir.toml # [workspace] members = ["packages/*", "apps/*"]
├── packages/
│ ├── core/ # ✓ Discovered (matches packages/*)
│ │ └── morphir.toml
│ ├── domain/ # ✓ Discovered (matches packages/*)
│ │ └── morphir.toml
│ └── deprecated-old/ # ✗ Excluded (matches deprecated-*)
│ └── morphir.toml
├── apps/
│ └── api/ # ✓ Discovered (matches apps/*)
│ └── morphir.toml
└── tools/
└── generator/ # ✗ Not discovered (no matching pattern)
└── morphir.toml
Discovery Algorithm
- Resolve
membersglobs relative to workspace root - Filter out paths matching
excludepatterns - For each remaining directory, check for configuration file
- Parse project config and register as workspace member
Workspace + Project Mode
A workspace root can also be a project itself:
# morphir.toml - Both workspace and project
[workspace]
members = ["packages/*"]
[project]
name = "my-org/workspace-root"
version = "1.0.0"
source_directory = "src"
This is useful when:
- The workspace root contains shared code
- You want a "meta" project that depends on all members
- Monorepo patterns where root is also a package
Configuration Inheritance
Member projects inherit configuration from the workspace:
# workspace/morphir.toml
[workspace]
members = ["packages/*"]
[ir]
format_version = 4
strict_mode = true
[codegen]
targets = ["typescript"]
# workspace/packages/core/morphir.toml
[project]
name = "my-org/core"
version = "1.0.0"
# Inherits [ir] and [codegen] from workspace
# Can override specific fields:
[codegen]
targets = ["typescript", "scala"] # Overrides workspace default
Inheritance Rules
| Section | Inheritance Behavior |
|---|---|
[morphir] | Merged (project can constrain further) |
[project] | Not inherited (project-specific) |
[workspace] | Not inherited (workspace-level only) |
[ir] | Merged (project overrides workspace) |
[codegen] | Merged (project overrides workspace) |
[cache] | Merged |
[logging] | Merged |
[tasks] | Merged (project can add/override) |
Shared Dependencies
Workspace-level dependencies can be defined for sharing across projects. This ensures consistent dependency versions across all workspace members.
# workspace/morphir.toml
[workspace]
members = ["packages/*"]
[workspace.dependencies]
# Repository dependencies (recommended)
"morphir/sdk" = { git = "https://github.com/finos/morphir-sdk.git", tag = "v3.0.0" }
"finos/morphir-json" = { git = "https://github.com/finos/morphir-json.git", tag = "v1.0.0" }
# Path dependencies for local packages
"my-org/shared" = { path = "packages/shared" }
Member projects reference shared dependencies using workspace inheritance:
# workspace/packages/domain/morphir.toml
[project]
name = "my-org/domain"
[dependencies]
"morphir/sdk" = { workspace = true } # Inherit from workspace
"my-org/shared" = { workspace = true } # Local workspace member
"other/lib" = { path = "../other" } # Project-specific path dependency
See Dependency Management for full documentation on dependency sources, resolution, and caching.
CLI Workspace Awareness
The CLI is workspace-aware regardless of the current working directory. When running commands from any subdirectory within a workspace, the CLI:
- Walks up the directory tree to find the workspace root (directory with
[workspace]in config) - Loads workspace configuration and discovers all member projects
- Determines context based on current directory:
- If in a member project directory: operates on that project by default
- If in workspace root: operates on workspace or default member
- If in non-member subdirectory: operates in workspace context
Workspace Discovery
workspace/ # Workspace root (config has [workspace])
├── morphir.toml
├── packages/
│ ├── core/
│ │ └── morphir.toml # Running `morphir build` here builds core
│ └── domain/
│ ├── morphir.toml
│ └── src/
│ └── User/ # Running `morphir build` here still builds domain
└── docs/ # Running `morphir workspace list` here works
Context Resolution
# From workspace root
~/workspace$ morphir build # Builds default_member or prompts
~/workspace$ morphir workspace build # Builds all members
# From member project
~/workspace/packages/core$ morphir build # Builds core
~/workspace/packages/core$ morphir workspace build # Builds all members
~/workspace/packages/core$ morphir workspace info # Shows workspace info
# From deep within a project
~/workspace/packages/domain/src/User$ morphir build # Builds domain
~/workspace/packages/domain/src/User$ morphir workspace list # Lists all members
# From non-member directory within workspace
~/workspace/docs$ morphir workspace list # Works - finds workspace root
~/workspace/docs$ morphir build # Error or uses default_member
Explicit Workspace/Project Selection
# Override automatic detection
morphir build --project my-org/core # Build specific project
morphir build --workspace # Force workspace-wide operation
morphir build --no-workspace # Force single-project mode (ignore workspace)
morphir --workspace-root /path/to/ws build # Explicit workspace root
Example: Full Workspace Configuration
# morphir.toml
[morphir]
version = "^4.0.0"
[workspace]
output_dir = ".morphir"
members = ["packages/*", "apps/*"]
exclude = ["packages/experimental-*"]
default_member = "packages/core"
[workspace.dependencies]
"morphir/sdk" = { git = "https://github.com/finos/morphir-sdk.git", tag = "v3.0.0" }
[ir]
format_version = 4
strict_mode = false
[codegen]
targets = ["typescript"]
output_format = "pretty"
[cache]
enabled = true
dir = ".morphir/cache"
[logging]
level = "info"
format = "text"
# Built-in tasks (build, test, check, etc.) work automatically
# Only define custom tasks or hooks
[tasks.ci]
description = "Run CI pipeline"
depends = ["check", "test", "build", "pack"]
run = "echo 'CI passed'"
[tasks."post:build"]
run = "prettier --write .morphir-dist/"
[tasks."post:codegen"]
run = "prettier --write generated/"
Best Practices
- Flat Structure: Prefer flat
packages/*over deeply nested hierarchies - Explicit Members: Use explicit patterns rather than catch-all
**/* - Shared Config: Put common settings at workspace level
- Default Member: Set
default_memberfor common single-project operations - Workspace Commands: Use
morphir workspaceprefix for explicit workspace operations