Skip to content

[Feature] Leo workspaces #29140

Description

@mohammadfawaz

🚀 Feature

Add a workspace concept to Leo, inspired by Cargo workspaces, that lets developers group related Leo programs under a single root directory and operate on them as a unit.

A minimal workspace.json at the project root declares the member programs:

{
    "members": ["token", "swap", "multisig"]
}

Each member remains a standard Leo package (its own program.json, src/main.leo, etc.). Running leo build, leo test, leo deploy, leo fmt, or leo clean from the workspace root applies the command to every member in dependency order.

Example layout

my-project/
├── workspace.json
├── token/
│   ├── program.json          # "token.aleo"
│   ├── src/main.leo
│   └── tests/
├── swap/
│   ├── program.json          # "swap.aleo", depends on token.aleo
│   ├── src/main.leo
│   └── tests/
└── multisig/
    ├── program.json          # "multisig.aleo", depends on token.aleo
    ├── src/main.leo
    └── tests/

Motivation

Aleo applications commonly consist of multiple interacting programs (e.g. a token contract, a swap program, and a multisig). Today each program is a fully independent package - there is no first-class way to manage them together. Developers must:

  • cd between directories to build, test, or deploy each program individually.
  • Manually order deployments to satisfy cross-program dependencies or use custom scripts.
  • Duplicate dependency declarations - if two programs depend on the same on-chain library, each must declare and fetch it independently.
  • Run formatters and linters per-package, making it easy to miss files.

Workspaces address all of these by providing a single entry point for multi-program projects.

Concrete benefits

Benefit Detail
Batch build leo build from root compiles all members in topological order. No manual sequencing.
Batch test leo test runs every member's test suite in one invocation.
Batch deploy leo deploy deploys all members in dependency order, reusing fee estimation across programs.
Batch format leo fmt formats every .leo file across all members.
Shared import cache Network dependencies fetched once and shared across members, avoiding redundant downloads.
Simplified inter-member deps A "workspace" dependency location resolves members by name without explicit relative paths.
Single clean leo clean removes all build artifacts across every member.
Project scaffolding leo new --workspace creates the workspace skeleton; leo new <name> inside a workspace adds a member.

Implementation

Workspace manifest — workspace.json

A new JSON file at the workspace root:

{
    "members": ["token", "swap", "multisig"]
}
  • members — ordered list of directory names, each containing a valid Leo package.
  • Glob support (e.g. "programs/*") can be added later.

Workspace discovery

When any CLI command runs, walk up from the current directory looking for workspace.json. If found, the workspace root is established. If the command is run from within a member directory, apply the command to that member only (unless --workspace is passed).

Inter-member dependencies - "location": "workspace"

A new dependency location variant alongside "local" and "network":

{
    "name": "token.aleo",
    "location": "workspace"
}

The resolver looks up the program name among workspace members and resolves the path automatically. This eliminates fragile relative "path" fields and makes manifests portable. Existing "local" paths continue to work for non-workspace dependencies.

CLI changes

Command Behaviour from workspace root Flag
leo build Build all members in dependency order --package <name> to target one member
leo test Test all members --package <name>
leo deploy Deploy all members in dependency order --package <name>, --skip <name>
leo fmt Format all members --package <name>
leo clean Clean all members --package <name>
leo new <name> Create member package, add to members --workspace to create a fresh workspace
leo add Add dependency to current member
leo remove Remove dependency from current member

Shared build cache

Workspace members share a top-level build/ directory (or the existing per-member build/ directories are preserved - TBD based on SnarkVM compatibility). At minimum, the ~/.leo/registry/ cache is shared so network dependencies are only fetched once.

Components affected

  • leo-package - new Workspace type, workspace.json parsing, Location::Workspace variant, workspace-aware dependency resolution.
  • leo/cli - workspace discovery in Context, --package / --workspace flags, iteration over members in build, test, deploy, fmt, clean commands.
  • leo/cli/commands/new.rs - workspace creation mode, member registration.

Phased rollout

  1. Phase 1 - MVP: workspace.json parsing, workspace discovery, leo build/test/fmt/clean iterate over members, --package flag.
  2. Phase 2 - Workspace deps: "location": "workspace" variant, automatic path resolution.
  3. Phase 3 - Deployment: leo deploy with workspace-aware ordering and shared fee estimation.
  4. Phase 4 - Ergonomics: glob members, leo new --workspace, auto-add member on leo new inside workspace, shared build directory.

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions