# Introduction and prerequisites Truffle uses [lerna](https://github.com/lerna/lerna) to manage multi-package repositories. Each Truffle module is defined in its own npm package in the `packages/` directory. The entry point of these modules is `@truffle/core`. This is where the command line parser is setup. Install lerna: ```shell $ npm install -g lerna $ npm install -g yarn ``` # The command flow The heart of Truffle lies in the `@truffle/core` package. Whenever a command is run, `packages/core/cli.js` gets run with everything following `truffle` (on the command line) being passed in as arguments. In other words, if you run `truffle migrate --network myNetwork`, then `packages/core/cli.js` gets run with "migrate" and "--network myNetwork" as arguments. Throughout the course of running `packages/core/cli.js`, Truffle parses out what commands and options the user has provided, instantiates an instance of the `Command` class, and calls the `run` method on that instance. The `run` method is the interface that `cli.js` uses for ALL commands. You can find all of the specific command files (one file for each command) at `packages/core/lib/commands`. From the run method of each command you should be able to trace the command lifecycle to libraries and modules in `@truffle/core` as well as other packages in the monorepo. # Add a new command in truffle ### Create a new lerna package ```shell $ lerna create mycmd ``` ### Add the package to `@truffle/core` ```shell $ lerna add mycmd --scope=@truffle/core ``` ### Create a new command in `@truffle/core` 1. Create a new directory in `packages/core/lib/commands/`, let's call it `mycmd`. 2. Create 3 javascript files inside the **mycmd** directory with the filenames **run.js**, **meta.js** and **index.js**: * **run.js** contains the entry function after a user calls your command. * **meta.js** contains information such as command name and command description. * **index.js** exports both the run module and the meta module. #### run.js ```shell $ cat << EOF > core/lib/commands/mycmd/run.js module.exports = async function (options){ const mycmd = require("mycmd"); // TODO: write the run command here, something like: // mycmd(options) }; EOF ``` #### meta.js ```shell $ cat << EOF > core/lib/commands/mycmd/meta.js module.exports = { command: "mycmd", description: "Run mycmd", builder: {}, help: { usage: "truffle mycmd", options: [] } EOF ``` #### index.js ```shell $ cat << EOF > core/lib/commands/mycmd/index.js module.exports = { run: require("./run"), meta: require("./meta") }; EOF ``` ### Link it from the commands/index.js file ```diff --- packages/core/lib/commands/index.js +++ packages/core/lib/commands/index.js @@ -1,4 +1,5 @@ module.exports = { + mycmd: require("./mycmd"), ``` ### Link it from the commands/commands.js file ```diff --- packages/core/lib/commands/commands.js +++ packages/core/lib/commands/commands.js @@ -1,4 +1,5 @@ module.exports = [ + "mycmd", ``` From there, you should see it in the help screen: ```shell $ cd packages/core $ node cli.js Truffle v5.0.0-beta.1 - a development framework for Ethereum Usage: truffle [options] Commands: mycmd Run mycmd build Execute build pipeline (if configuration present) [...] ``` ### Write your module/command The setup is done, you can now write your command and organize your module as you want in: `packages/mycmd/`. You can have a look at `packages/box/` which is a good starting example to follow. ### Execute the command ```shell $ cd packages/core $ node cli.js mycmd ```