Skip to content

Expose CLI commands as a programmatic library API - #512

Draft
tuler wants to merge 3 commits into
prerelease/v2-alphafrom
claude/cartesi-cli-library-api-2m3q2q
Draft

Expose CLI commands as a programmatic library API#512
tuler wants to merge 3 commits into
prerelease/v2-alphafrom
claude/cartesi-cli-library-api-2m3q2q

Conversation

@tuler

@tuler tuler commented Aug 7, 2026

Copy link
Copy Markdown
Member

Summary

This PR refactors the Cartesi CLI to expose all commands as a programmatic library API, allowing developers to use CLI functionality directly from TypeScript/JavaScript code without invoking the command-line interface.

import { build, depositErc20, hash, run, send } from "@cartesi/cli";

await build();
const node = await run({ epochLength: 10 });
await send({ input: "hello" });
await depositErc20({ amount: "1.5" });
await node.stop();

Key Changes

  • New API modules (apps/cli/src/api/): Created modular API functions for all commands:

    • build.ts - Build application drives and machine snapshot
    • run.ts - Start local Cartesi rollups environment
    • send.ts - Send inputs to deployed applications
    • deposit/ - Deposit assets: depositEther, depositErc20, depositErc721, depositErc1155, depositErc1155Batch
    • logs.ts - Stream environment logs
    • hash.ts - Get machine snapshot hash
    • status.ts - Query environment status
    • shell.ts - Boot machine in interactive mode
    • doctor.ts - Check system requirements
    • create.ts - Create new applications from templates
    • clean.ts - Clean build artifacts
    • address-book.ts - Get deployed contract addresses
    • connection.ts - Shared resolution of client, sender and application address
    • types.ts - Shared types and configuration resolution
  • Command refactoring: Updated all command files to delegate to the new API modules, eliminating code duplication. Commands keep the interactive prompts and pass resolved values to the API.

  • Library exports:

    • Added src/lib.ts as the main library entrypoint
    • Updated package.json to export both CLI (dist/index.js) and library (dist/lib.js) entrypoints
    • Added TypeScript declaration generation via tsconfig.build.json
  • Enhanced wallet support: Added interactive parameter to getRpcUrl() for programmatic use cases

  • Test coverage: Added unit tests for encodeInput(), resolveConfig(), parseAmount() and the deposit error hierarchy

  • Documentation: Updated README with library usage examples

Notable Implementation Details

  • API functions follow a consistent pattern with Options and Result types
  • Progress reporting is configurable (silent, default, verbose) for library use
  • Configuration can be provided as parsed Config objects or file paths
  • The run() function returns a RunResult object with methods to deploy/undeploy applications and stop the environment
  • All API functions are silent by default (no terminal output) unless progress option is specified
  • doctor() runs every check concurrently and returns all results, failed and successful, instead of stopping at the first failure
  • Deposit amounts are given in the base unit of the asset as a bigint, or in its display unit as a string ("1.5"); the token defaults to the corresponding devnet test token
  • Deposits that cannot be made throw DepositError subclasses (InsufficientBalanceError, InvalidAmountError, TokenNotFoundError) instead of printing and returning; the commands render them as before

Behavior Changes

  • run: "Build and redeploy" now builds with the configuration files given to run -c, instead of always cartesi.toml
  • deposit erc721: a failed ownership check that is not ERC721NonexistentToken now stops instead of reporting the failure and continuing
  • deposit erc1155-batch: the token-ids/amounts length mismatch is reported after the application address prompt, rather than before it

Testing

Type checking, linting and the 153 unit tests pass. A sample consumer was verified to type-check against the generated declarations under both bundler and nodenext module resolution, and importing dist/lib.js was verified to have no CLI side effects. Docker was not available in the development environment, so the docker-dependent paths (build, run, logs, deposits) were not exercised end to end and rely on CI.

https://claude.ai/code/session_015SA64hXXCsNWisTYLVpEBn

Every command is now also a function, so applications can be built, run
and inspected from a script:

    import { build, hash, run } from "@cartesi/cli";

The command actions were moved to `src/api`, and the Commander commands
became thin wrappers around them. The API functions take plain option
objects with defaults, return values instead of printing, throw instead
of exiting, and are silent unless `progress` is set to "default" or
"verbose", which reproduces the CLI output.

`src/lib.ts` is the new package entrypoint, bundled to `dist/lib.js` and
typed by `dist/types`, generated with `tsc --emitDeclarationOnly`. The
`bin` entrypoint is unchanged.

While rewiring the run command, "build and redeploy" now builds with the
configuration files given to `run`, instead of always `cartesi.toml`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015SA64hXXCsNWisTYLVpEBn
@changeset-bot

changeset-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 33b100c

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@cartesi/cli Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🟢 Lines 77.78% (🎯 0%) 5203 / 6689
🔵 Statements 77.78% 5203 / 6689
🔵 Functions 66.82% 145 / 217
🔵 Branches 0% 0 / 0
📁 File Coverage (20 files)
File Lines Statements Functions Branches Uncovered Lines
apps/cli/src/api/connection.ts 🔴 13.33% 🔴 13.33% 🔴 0% 🔴 0% 59-84
apps/cli/src/api/deposit/common.ts 🟢 93.1% 🟢 93.1% 🟡 71.43% 🔴 0% 90, 94
apps/cli/src/api/deposit/erc1155.ts 🔴 3.33% 🔴 3.33% 🔴 0% 🔴 0% 81-159, 170-262, 271-301
apps/cli/src/api/deposit/erc20.ts 🔴 7.07% 🔴 7.07% 🔴 0% 🔴 0% 33-46, 78-155
apps/cli/src/api/deposit/erc721.ts 🔴 5.51% 🔴 5.51% 🔴 0% 🔴 0% 40-49, 78-187
apps/cli/src/api/deposit/ether.ts 🔴 13.64% 🔴 13.64% 🔴 0% 🔴 0% 30-67
apps/cli/src/api/deposit/index.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/api/send.ts 🟡 71.96% 🟡 71.96% 🟢 80% 🔴 0% 46-47, 74-78, 95, 104, 156-176
apps/cli/src/api/types.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/base.ts 🔴 20.38% 🔴 20.38% 🔴 16.67% 🔴 0% 36, 40-45, 62, 72-78, 84-15...
apps/cli/src/builder/directory.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/builder/docker.ts 🟢 86.72% 🟢 86.72% 🟡 66.67% 🔴 0% 75-77, 79, 109-111, 169-178
apps/cli/src/builder/empty.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/builder/none.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/builder/tar.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/compose/anvil.ts 🔴 7.14% 🔴 7.14% 🔴 0% 🔴 0% 12-47, 51-52, 72-85
apps/cli/src/compose/builder.ts 🟢 99.79% 🟢 99.79% 🟢 100% 🔴 0% 228
apps/cli/src/compose/bundler.ts 🔴 4.82% 🔴 4.82% 🔴 0% 🔴 0% 8-40, 44-75, 79-92
apps/cli/src/compose/common.ts 🟢 100% 🟢 100% 🟢 100% 🔴 0% -
apps/cli/src/compose/database.ts 🔴 17.65% 🔴 17.65% 🔴 0% 🔴 0% 10-20, 24-26

claude added 2 commits August 7, 2026 16:22
The doctor API now runs every check in parallel and returns all results,
failed and successful, instead of stopping at the first failure and
reporting progress through callbacks. The command renders the results
after they are gathered.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015SA64hXXCsNWisTYLVpEBn
Adds `depositEther`, `depositErc20`, `depositErc721`, `depositErc1155`
and `depositErc1155Batch` to the library API, moving the deposit logic
out of the commands. The commands keep the prompts, and pass everything
resolved to the API.

Amounts are given in the base unit of the asset as a bigint, or in its
display unit as a string. Deposits that cannot be made now throw
`DepositError` subclasses instead of printing and returning, which the
commands render the same way as before.

The connection setup shared by `send` and the deposits (client, sender
and application address) moved to `resolveConnection`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015SA64hXXCsNWisTYLVpEBn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Todo

Development

Successfully merging this pull request may close these issues.

2 participants