moldx

A technology-agnostic orchestration engine that standardizes submodule lifecycle management through user-defined shell-based strategies.

Screenshot of moldx GitHub repository

Repository Details

Repo #1323352595
AuthorLorenzo Rottigni
Created At2026-08-04
Updated At2026-09-09
Pushed At2026-09-09
Size421 MB
Main LanguageRust
Star count0
Default branchmain

Repository Skills

README.md

MoldX

MoldX is a convention-based CLI for discovering project modules and running technology-specific workflows across them.

It detects the technologies and conventions present in a project, associates modules with profiles, and resolves the commands available for each module. Shell scripts serve as the default execution contract, keeping MoldX simple, portable, and easy to extend.

MoldX was created to solve a common problem in heterogeneous projects and monorepos: as modules adopt different languages, frameworks, and deployment strategies, project automation often grows into an increasingly complex collection of Makefiles, Bash scripts, and custom logic for determining which workflows apply to which modules.

MoldX turns this implicit project knowledge into a conventional, discoverable, and automatable structure.

Why MoldX?

Modern projects are rarely built around a single technology. A repository may contain Node.js applications, Rust services, Python workers, Docker configurations, and framework-specific projects side by side.

Each module may require different workflows:

  • a Rust service can be built and tested with Cargo;
  • a Node.js application can expose build and test commands;
  • a Nuxt application can additionally provide development and production commands;
  • a Docker-enabled module can be built, tagged, and deployed.

Traditional automation tools typically centralize this knowledge in configuration files, Makefiles, or custom scripts. As projects grow, these abstractions often become increasingly difficult to maintain and require explicit logic to determine which commands apply to each module.

MoldX takes a different approach: the structure of the project becomes the configuration.

Modules are discovered from the filesystem and associated with profiles based on conventions. Commands are then resolved dynamically from the profiles matched by each module.

A module is not limited to a single profile. For example, a service containing both a package.json and a Dockerfile can simultaneously expose Node.js and Docker workflows:

packages/api/
├── package.json
├── Dockerfile
└── ...
moldx test packages/api
moldx docker build packages/api
moldx docker deploy packages/api

This allows project automation to remain decentralized and technology-specific while still providing a consistent interface across the entire repository.

Getting Started

Installation

The release workflow publishes checksummed archives for Linux, macOS, and
Windows on both x86_64 and ARM64:

moldx-linux-x86_64-vX.Y.Z.tar.gz
moldx-linux-aarch64-vX.Y.Z.tar.gz
moldx-macos-x86_64-vX.Y.Z.tar.gz
moldx-macos-aarch64-vX.Y.Z.tar.gz
moldx-windows-x86_64-vX.Y.Z.zip
moldx-windows-aarch64-vX.Y.Z.zip
SHA256SUMS

Download the appropriate archive from the GitHub Releases page and verify it against SHA256SUMS.

On Linux or macOS, the setup script selects the current CPU architecture,
downloads the latest release archive, and verifies its checksum:

curl -fsSL https://raw.githubusercontent.com/LorenzoRottigni/moldx/main/bin/setup/install.sh | bash

To install a specific version or directory:

MOLDX_VERSION=v0.0.2 MOLDX_INSTALL_DIR="$HOME/.local/bin" \
    curl -fsSL https://raw.githubusercontent.com/LorenzoRottigni/moldx/main/bin/setup/install.sh | bash

On Windows PowerShell, run the setup script. It selects x86_64 or ARM64,
downloads the matching archive, verifies its checksum, and installs moldx.exe:

irm https://raw.githubusercontent.com/LorenzoRottigni/moldx/main/bin/setup/install.ps1 | iex

To install a specific Windows version:

$env:MOLDX_VERSION = "v0.0.3"
irm https://raw.githubusercontent.com/LorenzoRottigni/moldx/main/bin/setup/install.ps1 | iex

Note: Installation through package managers for common Linux distributions is planned.

Initialize a project

From the root of a Git repository:

moldx init

This creates the .moldx directory used by MoldX to store profiles, templates, commands, and shared libraries.

Example Project Structure

project/
├── .moldx/
│   ├── bin/ # moldx <command> <target>
│   │   ├── diff.sh
│   │   └── version.sh
│   │
│   ├── lib/ # shell utilities sourced by every command
│   │   └── common.sh
│   │
│   └── profiles/
│       ├── docker/
│       │   ├── template/ # matches modules containing a Dockerfile
│       │   │   └── Dockerfile
│       │   ├── lib/ # shell utilities sourced by docker commands
│       │   │   └── docker-utils.sh
│       │   └── bin/ # moldx docker <command> <target>
│       │       ├── build.sh
│       │       ├── run.sh
│       │       ├── push.sh
│       │       ├── tag.sh
│       │       └── deploy.sh
│       │
│       ├── rust/
│       │   ├── template/ # matches modules containing a Cargo.toml
│       │   │   └── Cargo.toml
│       │   └── bin/ # moldx rust <command> <target>
│       │       ├── build.sh
│       │       ├── test.sh
│       │       └── run.sh
│       │
│       ├── node/
│       │   ├── template/ # matches modules containing a package.json
│       │   │   └── package.json
│       │   ├── lib/ # shell utilities sourced by node commands
│       │   │   └── node-utils.sh
│       │   ├── bin/ # moldx node <command> <target>
│       │   │   ├── build.sh
│       │   │   └── test.sh
│       │   └── profiles/
│       │       ├── nuxt/
│       │       │   ├── template/ # matches modules containing package.json and nuxt.config.ts
│       │       │   │   ├── package.json
│       │       │   │   └── nuxt.config.ts
│       │       │   └── bin/ # moldx node nuxt <command> <target>
│       │       │       ├── dev.sh
│       │       │       └── start.sh
│       │       │
│       │       └── next/
│       │           ├── template/ # matches modules containing package.json and next.config.ts
│       │           │   ├── package.json
│       │           │   └── next.config.ts
│       │           └── bin/ # moldx node next <command> <target>
│       │               ├── dev.sh
│       │               └── start.sh
│       │
│       └── python/
│           ├── template/ # matches any module
│           ├── bin/ # moldx python <command> <target>
│           │   ├── lint.sh
│           │   └── test.sh
│           │
│           └── profiles/
│               ├── pip/
│               │   ├── template/ # matches modules containing requirements.txt
│               │   │   └── requirements.txt
│               │   └── bin/ # moldx python pip <command> <target>
│               │       ├── install.sh
│               │       ├── build.sh
│               │       └── run.sh
│               │
│               └── uv/
│                   ├── template/ # matches modules containing pyproject.toml
│                   │   └── pyproject.toml
│                   └── bin/ # moldx python uv <command> <target>
│                       ├── install.sh
│                       ├── build.sh
│                       └── run.sh
│
└── packages/

Glossary

Profile

A profile is a collection of commands related to a specific technology that can be applied to a particular type of module.

Profiles can be nested to provide more specific implementations for sub-technologies (for example, node > nuxt, node > next, or python > pip, python > uv).

Profiles are associated with modules through templates. A parent profile's template must be compatible with the templates of its child profiles.

Command

A command is an executable workflow managed by MoldX.

Commands are typically implemented as shell scripts and may belong to a specific profile or be profile-agnostic.

For example:

.moldx/profiles/docker/bin/build.sh

defines the build command for the docker profile.

Library

A library is a set of bash snippets shared by the commands of a profile.

Every profile may own a lib/ directory, and the project root may own a
.moldx/lib/ directory. Any .sh file inside them is sourced before a
command script runs, in a single shell, so helpers defined in a library (both
functions and variables) are available to the command:

.moldx/lib/common.sh
.moldx/profiles/node/lib/node-utils.sh
.moldx/profiles/node/profiles/nuxt/lib/nuxt-utils.sh

Commands receive the libraries of their own profile and of every ancestor
profile, loaded root-first. A node nuxt command therefore sources
common.sh, then node-utils.sh, then nuxt-utils.sh. Profile-agnostic
commands in .moldx/bin/ source only .moldx/lib/.

Template

A template describes the files that identify a module as belonging to a profile.

For example:

docker/
├── Dockerfile
└── compose.yml

A Docker template containing these files can be used to identify Docker modules.

Templates are not necessarily scaffolding templates in the traditional sense. Their primary purpose is to define conventions used for module detection.

Module

A module is a project directory that can be targeted by MoldX commands.

A module becomes associated with one or more profiles when it matches their templates.

A module may match multiple profiles.

For example:

packages/my-service/
├── package.json
├── Dockerfile
└── ...

could potentially match both the node and docker profiles.

Executor

An executor defines how a MoldX command is ultimately executed.

Shell is the default execution mechanism. Additional executors are planned for future versions.

CLI

moldx [OPTIONS...] [PROFILE...] <COMMAND> [MODULE] [-- <COMMAND_OPTIONS>...]

Runs a command against one or more modules.
For convenience, the module parameter is optional, allowing MoldX to support commands that are not tied to a specific module.

Profiles

Profiles can be specified to explicitly select the profile from which the command
should be resolved.

moldx docker build packages/server
moldx python uv build packages/worker

Profiles can be omitted. When a command is not qualified by a profile, MoldX
resolves it from the profiles matching the target module.

If multiple matching profiles provide a command with the requested name, MoldX
prompts the user to resolve the conflict.

moldx build packages/server

# STDIN
# -> python/uv/build
# -> python/pip/build
# -> docker/build

Command conflicts can be skipped using the --skip-conflicts option, avoiding
manual input.

Multiple Modules

Commands can target multiple modules using glob patterns.

moldx install packages/*

The * pattern is expanded by the shell and allows commands to target multiple modules at the same directory level.

MoldX also supports the ** pattern as a recursive module glob. Unlike standard shell glob expansion, MoldX interprets ** itself, allowing recursive module matching independently of the shell's globstar configuration.

# Match modules directly under packages/
moldx install packages/*

# Recursively match modules under packages/
moldx install packages/**

For each matching module, MoldX resolves the requested command independently from the profiles associated with that module.

Command Options

Arguments following -- are forwarded unchanged to the resolved command.

Positional command arguments are only supported after --.

moldx docker build packages/server -- --platform linux/amd64 --push

In this example, --platform linux/amd64 --push are passed directly to the
resolved docker/build command.

moldx [-- <OPTIONS>...] init <ENTITY> <PROFILE...> [ARGS...]

  • moldx init => creates .moldx/README.md, .moldx/bin/.keep, .moldx/lib/.keep, and .moldx/profiles/.keep
  • moldx init profile <...profile> => creates .moldx/profiles/<profile>/bin, .moldx/profiles/<profile>/lib, and .moldx/profiles/<profile>/template (supports nested profiles)
  • moldx init command [...profile] <command> => creates .moldx/profiles/<profile>/bin/<command> (supports nested profiles)
  • moldx init template [...profile] [...file_names] => creates .moldx/profiles/<profile>/template/<...file_names> (supports nested profiles)

Creating MoldX entities through the init command allows MoldX to validate input, enforce constraints, and prevent undefined or invalid configurations.

moldx list

Prints the state of the MoldX client after initialization, including available profiles, commands, templates, and resolved modules.

moldx

Runs the MoldX TUI in the current working directory.

Guidelines

.moldx Directory

MoldX requires a .moldx directory to be configured in order to operate.

MoldX is designed to work inside a Git repository, and the .moldx directory should normally be committed to version control.

The .moldx path can also be supplied explicitly through a command-line argument or environment variable, allowing MoldX to operate outside a Git repository.

By convention, MoldX expects .moldx to be located at the root of the repository.

If it is not found there, MoldX can search the Git workspace within the configured maximum resolution depth.

Once the .moldx directory has been resolved, MoldX commands can be invoked from anywhere within the Git workspace.

Module Resolution

MoldX resolves modules relative to the parent directory of the resolved .moldx directory.

Module discovery is recursive and limited by the configured maximum resolution depth.

This prevents MoldX from unnecessarily traversing the entire filesystem while still supporting common monorepo layouts.

Security

MoldX executes the scripts it discovers in .moldx on your machine with the
same privileges as the shell that runs moldx. Because the structure of the
project becomes the configuration, the .moldx directory is executable
code
, not inert metadata.

Trusting a project

Running moldx in a repository causes its .moldx/bin/*.sh command scripts
to be executed. Treat .moldx the same way you would treat the repository's
Makefile, package.json scripts, or CI workflows:

  • Only run moldx in repositories you trust.
  • Before running it in a repository you did not author, review the .moldx
    directory (especially bin/ command scripts and profile definitions).
  • Keep .moldx in version control, but be aware that cloning someone else's
    repository brings their .moldx scripts along with it.

None of these scripts are executed until you run a command that resolves them;
merely invoking moldx list or moldx detect discovers structure without
running any command script.

Environment variables

MoldX behavior can be redirected through environment variables such as
MOLDX_DIR (see Configuration). If you launch moldx in a
context where these variables are set by an untrusted source, MoldX may load
and later execute scripts from a directory you did not intend. When running
in non-interactive or CI contexts, pin MOLDX_DIR explicitly to the project
you intend to operate on.

What MoldX does not do

MoldX does not sandbox or isolate the scripts it executes. Command scripts
run with your full user privileges and can read, write, and execute anything
your user account can. Use standard precautions: run moldx as an
unprivileged user, and treat third-party .moldx definitions as untrusted
until reviewed.

Configuration

MoldX is designed to be configuration-light.

Project behavior is primarily inferred from the .moldx directory structure rather than from a central configuration file.

Global path-resolution and naming behavior can be customized through command-line arguments or environment variables.

Environment variable CLI option Default Description
MOLDX_DIR --moldx-dir ./.moldx Path to the MoldX directory
MOLDX_PROFILES_DIR_NAME --profiles-dir-name profiles Profiles directory name
MOLDX_BIN_DIR_NAME --bin-dir-name bin Commands directory name inside a profile
MOLDX_LIB_DIR_NAME --lib-dir-name lib Library snippets directory name inside a profile
MOLDX_TEMPLATES_DIR_NAME --templates-dir-name templates Command template file-names discovery directory
MOLDX_TEMPLATE_DIR_NAME --template-dir-name template Marker files directory used to identify a profile's modules
MOLDX_MODULES_DIR --modules-dir .moldx's parent Root directory scanned for modules (defaults to the parent of the resolved .moldx directory)
MOLDX_MAX_RESOLUTION_DEPTH --max-resolution-depth 20 Maximum recursion depth for .moldx and module resolution

Additionally, --skip-conflicts (a global flag with no environment variable)
automatically selects the first matching command when multiple profiles expose
the same command.

TUI

MoldX provides a terminal user interface capable of exposing MoldX's CLI functionality interactively.

The TUI is intended to make common operations easier to discover, particularly when:

  • multiple profiles match a module;
  • multiple commands are available;
  • users want to browse available modules;
  • users do not remember the exact CLI syntax.

Future versions may allow the TUI to connect to the MoldX daemon.

Roadmap

Executor Support

Introduce executors for execution targets other than the default shell executor.

Potential examples:

executors/
├── shell.sh
└── python.sh

An executor could wrap another runtime while preserving a common command interface.

A formal argument contract will be required to ensure that commands implemented using different executors receive parameters consistently.

Daemon

Add an optional MoldX daemon for long-running project interaction.

The proposed model is:

              ┌─────────────┐
CLI ─────────►│             │
              │ MoldX daemon│
TUI ─────────►│             │
              │             │
VS Code ─────►│             │
              └─────────────┘

When a daemon is running, CLI commands and the TUI can connect to it.

When no daemon is running, CLI commands should continue to work directly, while the TUI may optionally start one.

The daemon should primarily support stateful integrations and long-lived clients rather than being required for normal CLI execution.

VS Code Integration

Create a VS Code extension capable of connecting to the MoldX daemon.

Potential functionality includes:

  • browsing modules;
  • browsing profiles;
  • browsing available commands;
  • running commands;
  • viewing command output;
  • interacting with MoldX state.

Improved init

Make moldx init capable of detecting existing project conventions and scaffolding useful defaults.

For example, detecting:

package.json

could suggest or scaffold a Node.js profile with common commands such as:

test
dev
build
start

Similarly, other project manifests could be used to detect additional technologies.

This should remain opt-in or reviewable so that init does not unexpectedly modify an existing project.

Git Submodules

Explore using Git submodules to distribute reusable MoldX profiles outside individual monorepos.

This could allow teams to maintain shared profile collections independently from the projects consuming them.

Contributing

Contributions are welcome.

MoldX is still evolving, and contributions around CLI design, module resolution, profile conventions, executors, the TUI, and integrations are especially valuable.

Development

MoldX is written in Rust.

Typical development commands:

cargo build

cargo test

cargo run -- --help

See the repository's development documentation for the complete development workflow.

Playground

MoldX includes a playground for local experimentation.

When running MoldX locally:

cargo run -- list

MoldX automatically resolves the playground's .moldx directory, making it possible to test profiles, templates, commands, and module resolution without modifying the development environment itself.

The playground should be treated as an integration-testing environment for MoldX itself.

Testing

MoldX ships with three test suites that run automatically in CI on every push
and pull request:

  • Unit tests (cargo test --bin moldx) cover the core modules: profile and
    module resolution, template matching, command discovery, path discovery, the
    executor's process tracking, and the TUI state machine.
  • E2E tests (cargo test --test e2e) exercise the compiled binary against
    the playground monorepo, asserting that detect, list, and
    run behave correctly against real profiles, templates, and modules — for
    example multi-profile modules, nested profiles, glob matching, and conflict
    resolution.
  • README tests (cargo test --test readme) validate that the behaviors
    documented in this file (e.g. init, glob patterns, and command options)
    actually work as described.

CI also enforces cargo clippy --all-targets -- -D warnings, so the codebase
must be free of warnings to merge.

To run every test locally:

cargo test

Coverage is measured with cargo llvm-cov:

cargo llvm-cov

Release

At minimum, the release process should cover:

  1. updating the version;
  2. running the test suite;
  3. building release binaries;
  4. generating release artifacts;
  5. publishing the GitHub release;
  6. updating installation artifacts.

Versioning

MoldX should follow Semantic Versioning.

In general:

  • MAJOR versions may contain breaking changes;
  • MINOR versions add backwards-compatible functionality;
  • PATCH versions contain backwards-compatible fixes.

License

MoldX is licensed under the MIT License.

See the LICENSE file for the complete license text.