Project Model
This document explains how icp-cli discovers, loads, and consolidates your project configuration.
Project Structure
An icp-cli project is any directory containing an icp.yaml file. This file is the root of your project configuration.
The project layout is flexible but a typical layout will look like the one below. Notice that some of the directories
and configuration files are marked as optional: This is because the configuration can be split across multiple files
or inlined inside icp.yaml
my-project/├── icp.yaml # Project configuration├── networks/ # [Optional] network manifests│ ├── testnet1.yaml│ └── testnet2.yaml├── environments/ # [Optional] environment manifests│ ├── dev.yaml│ ├── production.yaml│ └── staging.yaml└── src/ # Canister source code └── canisters/ ├── frontend/ │ └── canister.yaml # [Optional] canister manifest └── backend/ └── canister.yaml # [Optional] canister manifestThe icp.yaml File
The icp.yaml file defines:
- Canisters — What to build and deploy
- Networks — Where to deploy (optional, defaults provided)
- Environments — Named deployment configurations (optional, defaults provided)
Minimal example:
canisters: - name: hello build: steps: - type: script commands: - cargo build --target wasm32-unknown-unknown --release - cp target/wasm32-unknown-unknown/release/hello.wasm "$ICP_WASM_OUTPUT_PATH"Network Discovery
Networks can be defined in three ways:
Implicit networks
There are two implicit networks defined:
local- is a local managed networkic- is the IC mainnet (connected network)
Their configuration is equivalent to:
networks: - name: ic configuration: mode: connected url: https://icp-api.io - name: local configuration: mode: managed gateway: host: localhost port: 8000Inline Definition
Define networks directly in icp.yaml
networks: - name: testnet configuration: mode: connected url: https://my-icp-testnet.io root-key: <some root key>External Files
Reference separate YAML files
networks: - networks/testnet1.yaml - networks/testnet2.yamlEnvironment Discovery
Environments can be defined in three ways:
Implicit Environments
There are two implicit environments:
local- uses the local managed networkic- uses the IC mainnet
They are defined like this:
environments: - name: local network: local - name: ic network: icInline Definition
Define environments directly in icp.yaml
environments: - name: my-staging-env network: mainnet - name: my-production-env network: mainnetExternal Files
Reference separate YAML files
environments: - env/my-staging-env.yaml - env/my-production-env.yamlCanister Discovery
Canisters can be defined in three ways:
Inline Definition
Define canisters directly in icp.yaml:
canisters: - name: my-canister build: steps: - type: script commands: - echo "Building..."External Files
Reference separate YAML files:
canisters: - frontend # look for frontend/canister.yaml - backend # look for backend/canister.yamlGlob Patterns
Discover canisters automatically:
canisters: - canisters/* # find all `canister.yaml` files in canisters/**Configuration Consolidation
icp-cli consolidates configuration from multiple sources into a single effective configuration. The order of precedence (highest to lowest):
- Environment-specific settings — Override everything for that environment
- Canister-level settings — Default settings for a canister
- Recipe-generated configuration — Expanded from recipe templates
- Implicit defaults — Built-in networks and environments
View the effective configuration:
# outputs the effect project configuration in yamlicp project show
# You can use yq to view the effective settings of a canister# in a particular environment. Here we're looking at the settings# in the 'local' enviromenticp project show | yq -r ".environments.local"Canister IDs
When you deploy, icp-cli records canister IDs in mapping files. The location depends on the network type:
- Managed networks (eg: local):
.icp/cache/mappings/<environment>.ids.json - Connected networks (eg: mainnet):
.icp/data/mappings/<environment>.ids.json
Each environment maintains separate canister IDs, so your local deployment and mainnet deployment have different IDs.
The mapping file for managed networks is ephemeral, meaning that it will be removed when the network is stopped.
Project Root Detection
icp-cli looks for icp.yaml in the current directory and parent directories. You can override this:
icp deploy --project-root-override /path/to/projectNext Steps
- Build, Deploy, Sync — The deployment lifecycle