Custom Commands 
Whether developing Semo plugins or building applications and tool scripts based on Semo, adding Semo command lines is almost unavoidable before encapsulating plugins. To achieve a smooth development experience, Semo has been continuously optimizing the entire process, and this is still ongoing. This article explains how to define commands under Semo.
Preparation Phase 
As will be mentioned later, we don't need to create command code templates ourselves; it's entirely repetitive work. Therefore, a command-line code generator is provided. But where should this code be placed? First, it needs to be declared. The configuration file recognized by Semo here is .semorc.yml, and the effective configuration is commandDir. Sometimes the project is based on TS, requiring configuration of a TS command-line directory commandMakeDir. Sometimes you are writing subcommands for commands defined by other plugins; in this case, the corresponding extendDir and extendMakeDir need to be defined.
Taking plugin development as an example, the configuration file is roughly as follows:
typescript: true
commandDir: lib/commands
commandMakeDir: src/commands
extendDir: lib/extends
extendMakeDir: src/extendsThe Command for Creating Commands 
Semo has a built-in code generation mechanism, including a code generation command for adding new commands:
semo generate command COMMAND_NAME COMMAND_DESCRIPTIONCommand-line Code Template Example 
Here is an example using the TS version command:
semo generate command test 'test description'export const disabled = false // Set to true to disable this command temporarily
// export const plugin = '' // Set this for importing plugin config
export const command = 'test'
export const desc = 'test description'
// export const aliases = ''
// export const middlewares = (argv) => {}
export const builder = function (yargs: any) {
  // yargs.option('option', { default, describe, alias })
  // yargs.commandDir('test')
}
export const handler = async function (argv: any) {
  console.log('Start to draw your dream code!')
}As you can see, compared to commands in the yargs framework, there are some differences. Since Semo is based on yargs, the differences here are customizations based on yargs's extensibility.
Explanation of Command-line Attributes 
disabled or disable 
This indicates whether the command is disabled. When disabled, it is not only invisible but also inactive. Mainly used in scenarios where you want to disable a command without deleting the code.
command, desc, aliases, builder, handler 
These attributes are part of the yargs command specification and are easy to understand, requiring no further explanation. You can refer to the yargs related documentation
desc can also be written as description or describe.
middlewares 
Yes, middlewares are supported here. The benefit is that you can extract similar processing logic into middlewares and reuse the code across multiple commands. Generally needed only in complex business scenarios.
plugin 
This is an attribute specific to Semo plugins. If you define a command within a plugin, declaring this allows you to retrieve specific configurations from the global configuration file via argv.$core.getPluginConfig.
~/.semo/.semorc.yml
$plugin:
  test:
    a: 1In the code, you can:
const a = argv.$core.getPluginConfig('a', 1)Internally, it will calculate which plugin's configuration to retrieve the value from.
Regarding Subcommands 
Notice the line in the code template:
yargs.commandDir('test')The effect of this line is to look for subcommands in the test directory. There is a drawback here: when a plugin wants other plugins to extend this subcommand, other plugins cannot do so. How can it be done? Semo has wrapped this method.
const argv = await yargs.argv
await argv.$core?.extendSubCommand('test', 'semo-plugin-test', yargs, __dirname)The key here is that the first two parameters must be filled in correctly. Then, how do other plugins extend the subcommand? When creating the command, write it like this:
semo generate command test/subcommand --extend=semo-plugin-test