Skip to content

Tutorial 04 Packages and CLI Workflow

Tawan edited this page Jun 15, 2026 · 8 revisions

Small experiments can be compiled as single .cell files. Once a contract has more than one source file, a dependency, or a release target, use a package.

A package gives the compiler a stable place to find the entry file, build settings, dependencies, and lockfile. That makes builds repeatable for you, and reviewable for someone else.

What You Will Learn

  • how to create a package;
  • what belongs in Cell.toml;
  • how to build, check, format, and document a package;
  • which reports are useful during review;
  • where the current package workflow intentionally stops.

Create a Package

Create an application-style package:

cellc init my_contract
cd my_contract

This creates a Cell.toml manifest and a source entry. Use this form when you want a contract package with a concrete entry.

Create a library-style package:

cellc init my_lib --lib

Ask for a machine-readable summary when scripting:

cellc init my_contract --json

Read The Manifest

A minimal manifest looks like this:

[package]
name = "my_contract"
version = "0.1.0"
edition = "2021"
entry = "src/main.cell"

[build]
target = "riscv64-elf"
target_profile = "ckb"
out_dir = "build"

[dependencies]
my_lib = { path = "../my_lib" }

Read the manifest as a build promise:

  • entry tells the compiler where the package starts;
  • target chooses assembly or ELF-style output;
  • target_profile chooses the runtime assumptions;
  • out_dir chooses where artifacts are written;
  • path dependencies keep local packages explicit.

Registry publishing and registry dependency resolution are intentionally experimental/fail-closed until a trusted registry path is ready. Local path dependencies are the supported workflow for repeatable local development.

When registry resolution is enabled, cellc add must remain a dependency resolver, not a code-snippet finder. Anything reachable by cellc add must be safe to participate in the package, build, deployment, or declared TCB identity chain. Template-only material belongs behind copy/scaffold commands instead.

Build

Run the package build:

cellc build

Useful flags:

cellc build --target riscv64-asm
cellc build --target riscv64-elf
cellc build --target-profile ckb
cellc build --production
cellc build --json

build reads Cell.toml, compiles the current package entry, and writes the artifact plus metadata sidecar under the configured output directory.

For a one-off source file, use the top-level compiler form instead:

cellc path/to/file.cell

That form is great for quick experiments. Packages are better when you need repeatability.

Check Without Writing Artifacts

Use check when you want fast feedback:

cellc check
cellc check --all-targets
cellc check --target-profile ckb
cellc check --production
cellc check --deny-runtime-obligations
cellc check --json

check --all-targets is useful before committing. It catches source and profile problems without producing build artifacts.

Format And Generate Docs

Format the package:

cellc fmt
cellc fmt --check
cellc fmt --json

Generate package docs:

cellc doc
cellc doc --json

Generated docs summarize modules, actions, resources, receipts, locks, flow rules, and lowering metadata.

Audit And Evidence Reports

When a package is ready for review, ask the compiler for the facts it already knows:

cellc metadata . --target riscv64-elf --target-profile ckb -o build/main.metadata.json
cellc constraints . --target riscv64-elf --target-profile ckb -o build/main.constraints.json
cellc abi . --target-profile ckb
cellc scheduler-plan . --target-profile ckb --json
cellc opt-report . --target riscv64-elf --target-profile ckb --json

For CKB-specific builder and deployment review:

cellc constraints . --target riscv64-elf --target-profile ckb --json
cellc abi . --target-profile ckb --action transfer
cellc entry-witness . --target-profile ckb --action transfer --json
cellc ckb-hash --file build/main.elf
cellc verify-artifact build/main.elf --expect-target-profile ckb --verify-sources --production

These reports are not busywork. They answer questions reviewers will ask:

  • what is the entry ABI;
  • what witness layout is expected;
  • what capacity or runtime obligations remain;
  • what CKB hash policy is being used;
  • whether the artifact still matches the source and metadata.

They do not replace chain acceptance reports, builder-generated transactions, occupied-capacity evidence, or CKB production gates.

Local Dependencies

Add a local dependency:

cellc add my_lib --path ../my_lib

add --path records the dependency in Cell.toml. To resolve the dependency graph and write Cell.lock, run:

cellc install

You can also add and lock a local dependency in one command:

cellc install my_lib --path ../my_lib

Git dependencies must be pinned to a full commit hash:

cellc add math --git https://example.com/math.git --rev 0123456789abcdef0123456789abcdef01234567
cellc install math --git https://example.com/math.git --rev 0123456789abcdef0123456789abcdef01234567

Branch, tag, and default-branch git dependencies are rejected because they can move without changing Cell.toml.

Remove it:

cellc remove my_lib

install, update, and normal dependency removal refresh the lockfile so direct and transitive local path dependencies stay consistent.

Registry Resolver Boundaries

CellScript's registry design follows the same split as the package identity model:

  • package identity answers which source was referenced;
  • build identity answers which artifact and metadata were produced;
  • deployment identity answers which CKB Cell, CellDep, or runtime artifact is being used.

Registry discovery can be broad. It may index CellScript source packages, runtime verifiers, deployed CKB artifacts, reproducible artifacts, and even external CKB tooling artifacts such as bootstrapper outputs. Resolver profiles must stay narrower: an object can be discovered without being installable by cellc add.

That means registry resolution is stricter than discovery. The future resolver path should accept only objects that can be checked fail-closed:

Kind cellc add Boundary
source_package / library yes Source and API identity must be pinned and reproducible.
runtime_verifier / spawn-verifier yes TCB object; requires verifier ID, ABI, artifact identity, build profile, security status, and production deployment pins when used in production.
deployable_contract yes Must expose build/audit/deployment identity, not just source text.
deployed_artifact_record yes Must bind network, OutPoint, dep type, code/data hash, and status.
reproducible_artifact yes, if artifact-safe Must bind source hash, build profile hash, artifact hash, and compatibility profile.
protocol_profile_library yes, if resolver-safe Must be a real package with checkable source/schema/API semantics.
template, cookbook, protocol_skeleton, scaffold no Copy-only starting material; after copying, it becomes local project code.

The rule is intentionally blunt:

Discovery can be broad; dependency resolution is narrow.

Anything reachable by cellc add must be dependency-safe, artifact-safe,
deployment-fact-safe, or declared-TCB-safe.

Anything scaffold-only must be copied, not resolved.

For example, a BIP340 verifier package can have no business parameters and still be resolver-safe because it is a runtime verifier artifact. Its manifest or registry record must identify the verifier capability, IPC ABI, artifact hashes, build profile, TCB/security status, and any production CellDep pins.

A NovaSeal starter project, by contrast, is not dependency-safe merely because it contains useful .cell code. If users are expected to copy it and edit terms, authorities, manifests, or deployment pins, it belongs in a cookbook or template flow such as:

cellc new my_agreement --template novaseal/mvb-starter
cellc cookbook copy novaseal/agreement-profile ./my-agreement

It should not be installed with:

cellc add novaseal/mvb-starter

This keeps the registry as a verifiable dependency and artifact discovery layer, not a general examples marketplace.

Package Information

cellc info
cellc info --json

Use info when you want a quick view of the package boundary before building or debugging dependency resolution.

Experimental Commands

Registry publishing, registry package installation, login, run, and repl remain experimental/future-facing. Local install --path and update are supported as lockfile helpers for local path dependency workflows.

Next

With a repeatable package workflow in place, continue with CKB Target Profiles.

Clone this wiki locally