--- sidebar_position: 6 --- # Command plugins MycroForge has a plugin system that allows you to extend the CLI with your own commands. This section will guide you through the process of creating your own extension to the `m4g` command. MycroForge is written in C# sharp and this is the same for plugins, so decent knowledge about `C#` & `.NET` is required. In this tutorial we will create a command plugin that extens the `m4g` command with a `dotenv` sub command. What this command will do is generate a `.env` file in the current directory and print a message to the console. ## Setup To start creating command plugins for MycroFroge, make sure you've added the devdisciples package repository. This can be done by running the following command. ``` dotnet nuget add source --name devdisciples https://git.devdisciples.com/api/packages/devdisciples/nuget/index.json ``` Run the following command to add the `MycroForge.PluginTemplate.Package`. ``` dotnet add package --source devdisciples --version 1.0.0 MycroForge.PluginTemplate.Package ``` ## Initialize a plugin package Generate a template plugin project by running the following command. ``` m4g plugin init My.Dotenv.Plugin ``` This should generate the following folder structure. ``` My.Dotenv.Plugin ┣ 📜HelloWorldCommand.cs ┣ 📜HelloWorldCommandPlugin.cs ┗ 📜My.Dotenv.Plugin.csproj ``` Rename the following files. Also rename the classes in these files, the easiest way in `vscode` is to right click the class name and select the `Rename symbol` action. Note that this action does not (necessarily) rename the files! ``` HelloWorldCommand.cs => DotenvCommand.cs HelloWorldCommandPlugin.cs => DotenvCommandPlugin.cs ``` Modify `Name` property in `DotenvCommandPlugin.cs`. ```cs // Before public class DotenvCommandPlugin : ICommandPlugin { public string Name => "My.Plugin"; public void RegisterServices(IServiceCollection services) { services.AddScoped, HelloWorldCommand>(); } } // After public class DotenvCommandPlugin : ICommandPlugin { public string Name => "My.Dotenv.Plugin"; public void RegisterServices(IServiceCollection services) { services.AddScoped, HelloWorldCommand>(); } } ``` Modify `DotenvCommand.cs`. ```cs // Before public class DotenvCommand : Command, ISubCommandOf { private readonly Argument NameArgument = new(name: "name", description: "The name of the person to greet"); private readonly Option AllCapsOption = new(aliases: ["-a", "--all-caps"], description: "Print the name in all caps"); private readonly ProjectContext _context; public DotenvCommand(ProjectContext context) : base("hello", "An example command generated by dotnet new using the m4gp template") { _context = context; AddArgument(NameArgument); AddOption(AllCapsOption); this.SetHandler(ExecuteAsync, NameArgument, AllCapsOption); } private async Task ExecuteAsync(string name, bool allCaps) { name = allCaps ? name.ToUpper() : name; await _context.CreateFile("hello_world.txt", $"Hello {name}!", "This file was generated by your custom command!" ); } } // After public class DotenvCommand : Command, ISubCommandOf { private readonly Argument VarsArgument = new(name: "vars", description: "Env vars to include in the .env file separated by ';'"); private readonly Option PrintOption = new(aliases: ["-o", "--overwrite"], description: "Overwrite the .env file if it exists"); private readonly ProjectContext _context; public DotenvCommand(ProjectContext context) : // dotenv = the name of the sub command that will be added to the m4g command base("dotenv", "Generate a .env file in the current directory") { _context = context; AddArgument(VarsArgument); AddOption(PrintOption); this.SetHandler(ExecuteAsync, VarsArgument, PrintOption); } private async Task ExecuteAsync(string vars, bool overwrite) { var path = Path.Join(Environment.CurrentDirectory, ".env"); if (File.Exists(path)) { if (overwrite) { await _context.WriteFile(".env", content); return; } Console.WriteLine($"File {path} already exists, add the -o or --overwrite flag to overwrite it."); } var content = string.Join(Environment.NewLine, vars.Split(';')); await _context.CreateFile(".env", content); } } ``` ## Install the plugin Open a terminal an make sure you're in the root directory of the plugin, i.e. the `My.Dotenv.Plugin` folder. Run the following command to install the plugin. ``` m4g plugin install --platform ``` Make sure to choose the right platform option for your machine. If everything went well then running `m4g` should now also show a `dotenv` command. ## Test the plugin Try running `m4g dotenv "FIRSTNAME=JOHN;LASTNAME=JOE"`, this should generate a `.env` in the current directory with the vars you specified. ## Uninstall the plugin Uninstall the plugin by running `m4g plugin install My.Dotenv.Plugin`. ## Resources For examples of how the core commands are implemented, you can take a look at the commands in the [MycroForge.CLI.Commands](https://git.devdisciples.com/devdisciples/mycroforge/src/branch/main/MycroForge.CLI/Commands) namespace. The MycroForge.CLI project uses [SystemCommand.Line](https://learn.microsoft.com/en-us/dotnet/standard/commandline/get-started-tutorial) for the CLI support, check out the Microsoft documentation for more info.