Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions .claude/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

`icp-cli-recipes` contains official build recipe templates for Internet Computer (ICP) canisters. Recipes provide standardized, reusable build configurations using Handlebars templates.

## Repository Structure

```
recipes/
├── rust/ # Rust canister recipe
│ ├── recipe.hbs # Handlebars template
│ └── README.md # Documentation
├── motoko/ # Motoko canister recipe
├── prebuilt/ # Pre-built WASM recipe
└── asset-canister/ # Asset canister recipe
```

## Recipe Template Structure

Each recipe is a Handlebars template (`.hbs`) that generates YAML build/sync configuration:

```handlebars
{{! Documentation comments for parameters }}
{{! `param: type` Description }}

build:
steps:
- type: script
commands:
- command using {{ param }}

{{#if optional_param}}
- type: script
commands:
- conditional command
{{/if}}
```

## Key Patterns

### Required vs Optional Parameters

- **Required parameters**: Used directly as `{{ param }}` - will cause strict mode error if missing
- **Optional parameters**: Wrapped in conditionals `{{#if param}}{{ param }}{{/if}}`

### Common Configuration Options

Most recipes support these optional parameters:
- `shrink: boolean` - Optimize WASM with ic-wasm shrink
- `compress: boolean` - Gzip compress the WASM
- `metadata: array` - Custom metadata key-value pairs

## Documentation Verification

**IMPORTANT**: When modifying recipes, always verify:

1. **Template matches README**: Every parameter in `recipe.hbs` must be documented in the README
2. **Required vs Optional**: Parameters used directly (not in `{{#if}}`) are required - document accordingly
3. **Config option descriptions**: Each parameter must accurately describe what it does, verified against the actual behavior in `recipe.hbs`. For example, if `shrink` runs `ic-wasm shrink`, the description should reflect what that command does ("Remove unused functions and debug info to reduce file size")
4. **YAML syntax in examples**: Use `canisters: - name:` array syntax, not `canister:`
5. **Recipe type format**: Use `@dfinity/<recipe-name>`, not just `<recipe-name>`
6. **Prerequisites accuracy**: List actual dependencies (mops vs moc, ic-wasm requirements, etc.)
7. **Build process accuracy**: Document what the recipe actually does, step by step

### Cross-Repository Verification

This repository is used by `icp-cli`. When making changes:

1. Check `icp-cli/docs/guides/using-recipes.md` for recipe usage examples
2. Check `icp-cli/examples/` for example projects using recipes
3. Ensure documentation in both repos stays in sync

## Testing Changes

Since recipes are Handlebars templates, test by:

1. Creating a test project with `icp.yaml` using the recipe
2. Running `icp project show` to see the expanded configuration
3. Running `icp build` to verify the build works
26 changes: 13 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ Official build recipe templates for Internet Computer (ICP) canisters. Recipes p
Reference a recipe in your `icp.yaml` file:

```yaml
canister:
name: backend
recipe:
type: "@dfinity/rust"
configuration:
package: my-canister
shrink: true
canisters:
- name: backend
recipe:
type: "@dfinity/rust"
configuration:
package: my-canister
shrink: true
```

### Recipe Naming Convention
Expand All @@ -42,12 +42,12 @@ Recipes follow the `@dfinity/<recipe-name>` naming pattern:
To pin to a specific recipe version, append `@<version>` to the recipe type:

```yaml
canister:
name: backend
recipe:
type: "@dfinity/rust@v3.0.0"
configuration:
package: my-canister
canisters:
- name: backend
recipe:
type: "@dfinity/rust@v3.0.0"
configuration:
package: my-canister
```

Without a version specified, the latest stable version is used. View available versions in the [releases page](https://github.com/dfinity/icp-cli-recipes/releases).
Expand Down
70 changes: 36 additions & 34 deletions recipes/asset-canister/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,61 +7,63 @@ Download and configure the official IC assets canister with asset synchronizatio
Example of how to reference this recipe in an `icp.yaml` file:

```yaml
canister:
name: frontend
recipe:
type: "@dfinity/asset-canister"
configuration:
version: 0.30.2
dir: dist
canisters:
- name: frontend
recipe:
type: "@dfinity/asset-canister"
configuration:
version: 0.30.2
dir: dist
```

## Configuration Parameters

| Parameter | Type | Required | Description | Default |
|-----------|------|----------|-------------|---------|
| version | string | No | SDK version tag to download assets canister from | latest |
| dir | string | Yes | Directory containing frontend assets to synchronize | - |
| build | array | No | Commands to build the frontend assets | [] |
| metadata | array | No | Array of key-value pairs for custom metadata | [] |
| version | string | No | SDK version tag to download the assets canister from (e.g., `0.30.2`) | latest |
| dir | string | Yes | Directory containing frontend assets to synchronize to the canister | - |
| build | array | No | Shell commands to build the frontend assets before deployment (e.g., `npm run build`) | [] |
| metadata | array | No | Array of key-value pairs for custom metadata to inject into the WASM | [] |

## Prerequisites

- `ic-wasm` tool must be installed for metadata injection and optimization
- Frontend assets must either exist in the specified directory or be built using provided commands
- Frontend assets must either exist in the specified directory or be built using provided `build` commands
- Internet connection required to download the assets canister WASM
- `ic-wasm` (included with icp-cli installation) - only required if using `metadata` option

> **Note:** If you followed the [icp-cli installation guide](https://github.com/dfinity/icp-cli#installation), `ic-wasm` is already installed.

## Examples

### Basic Example

```yaml
canister:
name: website
recipe:
type: "@dfinity/asset-canister"
configuration:
dir: build
canisters:
- name: website
recipe:
type: "@dfinity/asset-canister"
configuration:
dir: build
```

### Advanced Example

```yaml
canister:
name: spa-frontend
recipe:
type: "@dfinity/asset-canister"
configuration:
version: 0.30.2
build:
- npm install
- npm run build
dir: dist
metadata:
- name: "frontend:framework"
value: "react"
- name: "frontend:version"
value: "1.0.0"
canisters:
- name: spa-frontend
recipe:
type: "@dfinity/asset-canister"
configuration:
version: 0.30.2
build:
- npm install
- npm run build
dir: dist
metadata:
- name: "frontend:framework"
value: "react"
- name: "frontend:version"
value: "1.0.0"
```

## Build Process
Expand Down
89 changes: 46 additions & 43 deletions recipes/motoko/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,78 +7,81 @@ Compile Motoko source code using the moc compiler to create IC canisters.
Example of how to reference this recipe in an `icp.yaml` file:

```yaml
canister:
name: backend
recipe:
type: "@dfinity/motoko"
configuration:
entry: src/main.mo
shrink: true
canisters:
- name: backend
recipe:
type: "@dfinity/motoko"
configuration:
main: src/main.mo
shrink: true
```

## Configuration Parameters

| Parameter | Type | Required | Description | Default |
|-----------|---------|----------|----------------------------------------------|---------------------------|
| entry | string | Yes | Path to the main Motoko source file | (autogenerated interface) |
| candid | string | No | Path to the Candid interface file | |
| metadata | array | No | Array of key-value pairs for custom metadata | [] |
| shrink | boolean | No | Enable WASM optimization to reduce file size | false |
| compress | boolean | No | Enable gzip compression of WASM file | false |
| Parameter | Type | Required | Description | Default |
|-----------|---------|----------|----------------------------------------------|---------|
| main | string | Yes | Path to the main Motoko source file | |
| args | string | No | Additional arguments to pass to moc compiler (e.g., `--incremental-gc`) | |
| candid | string | No | Path to a custom Candid interface file. If not provided, the interface is auto-generated by the Motoko compiler | (auto-generated) |
| metadata | array | No | Array of key-value pairs for custom metadata | [] |
| shrink | boolean | No | Remove unused functions and debug info to reduce file size | false |
| compress | boolean | No | Gzip compress the WASM file | false |

## Prerequisites

- `moc` (Motoko compiler) must be installed
- `ic-wasm` tool must be installed for metadata injection and optimization
- Motoko source files must be available in your project
- `mops` (Motoko package manager) - this recipe uses `mops toolchain` to manage the Motoko compiler
- `ic-wasm` (included with icp-cli installation)

### Installation
> **Note:** If you followed the [icp-cli installation guide](https://github.com/dfinity/icp-cli#installation), both `mops` and `ic-wasm` are already installed.

To install the Motoko compiler, see: <https://internetcomputer.org/docs/building-apps/getting-started/install>
### Additional Installation

If mops is not installed, see: <https://mops.one/docs/install>

## Examples

### Basic Example

```yaml
canister:
name: hello-world
recipe:
type: "@dfinity/motoko"
configuration:
entry: src/main.mo
canisters:
- name: hello-world
recipe:
type: "@dfinity/motoko"
configuration:
main: src/main.mo
```

### Advanced Example

```yaml
canister:
name: complex-backend
recipe:
type: "@dfinity/motoko"
configuration:
entry: src/backend.mo
shrink: true
compress: true
metadata:
- name: "canister:type"
value: "backend"
- name: "language:version"
value: "0.10.0"
canisters:
- name: complex-backend
recipe:
type: "@dfinity/motoko"
configuration:
main: src/backend.mo
args: --incremental-gc
shrink: true
compress: true
metadata:
- name: "canister:type"
value: "backend"
- name: "language:version"
value: "0.10.0"
```

## Build Process

When this recipe is executed:

1. Checks if the Motoko compiler (`moc`) is installed
2. Compiles the specified Motoko entry file using `moc`
3. Moves the resulting WASM file to the output location
1. Checks if `mops` is installed (used for Motoko toolchain management)
2. Compiles the specified Motoko entry file using `moc` via `mops toolchain`
3. Handles Candid interface: auto-generates from Motoko source, or uses the provided `candid` file
4. Injects compiler version metadata ("moc:version")
5. Injects template type metadata ("template:type" = "motoko")
6. Injects any custom metadata specified in the configuration
7. Optionally optimizes the WASM file if `shrink` is enabled
8. Optionally compresses the WASM file if `compress` is enabled
7. Optionally removes unused functions if `shrink` is enabled
8. Optionally gzip compresses the WASM file if `compress` is enabled

## Project Structure

Expand Down
5 changes: 3 additions & 2 deletions recipes/motoko/recipe.hbs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
{{! A recipe for building a Motoko canister }}
{{! `main: string` Motoko file which contains the main actor }}
{{! `args: string` Additional arguments to pass to the moc compiler }}
{{! `candid: string` Optional, the path to the Candid interface file }}
{{! `shrink: boolean` Optimizes the wasm with ic-wasm }}
{{! `compressed: boolean` determins whether the was should be gzipped }}
{{! `compress: boolean` determines whether the wasm should be gzipped }}
{{! `metadata: [name: string, value: string]`: An array of name/value pairs that get injected into the wasm metadata section }}

build:
steps:
- type: script
commands:
- sh -c 'command -v mops >/dev/null 2>&1 || { echo >&2 "'mops' not found on path. To install Mops, see https://mops.one/docs/install.\n"; exit 1; }'
- sh -c '$(mops toolchain bin moc) "{{ main }}" {{ args }} {{#if candid}}--omit-metadata{{else}}--public-metadata{{/if}} candid:service $(mops sources) -o "$ICP_WASM_OUTPUT_PATH"'
- sh -c '$(mops toolchain bin moc) "{{ main }}" {{#if args}}{{ args }} {{/if}}{{#if candid}}--omit-metadata{{else}}--public-metadata{{/if}} candid:service $(mops sources) -o "$ICP_WASM_OUTPUT_PATH"'

- type: script
commands:
Expand Down
Loading