{"id":16639415,"url":"https://github.com/deviousasti/netshell","last_synced_at":"2026-05-08T03:03:12.611Z","repository":{"id":151554994,"uuid":"219336502","full_name":"deviousasti/netshell","owner":"deviousasti","description":"Easily create a shell for your existing .NET APIs","archived":false,"fork":false,"pushed_at":"2020-09-15T10:28:03.000Z","size":144,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-18T12:19:59.900Z","etag":null,"topics":["apis","dotnet","readline","shell","strongly-typed"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/deviousasti.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-03T17:12:54.000Z","updated_at":"2023-03-06T06:19:40.000Z","dependencies_parsed_at":"2023-06-01T18:45:57.376Z","dependency_job_id":null,"html_url":"https://github.com/deviousasti/netshell","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fnetshell","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fnetshell/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fnetshell/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/deviousasti%2Fnetshell/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/deviousasti","download_url":"https://codeload.github.com/deviousasti/netshell/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243147275,"owners_count":20243744,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["apis","dotnet","readline","shell","strongly-typed"],"created_at":"2024-10-12T07:06:01.440Z","updated_at":"2025-12-27T06:37:22.827Z","avatar_url":"https://github.com/deviousasti.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# netshell\n\nCreate a bash-like shell for your APIs\n\n## 10-second intro\n\nnetshell maps methods into shell commands.\n\n```csharp\n[Command(\"echo\")]\npublic void Echo(string text, ConsoleColor color = ConsoleColor.White)\n{\n\tConsole.ForegroundColor = color;\n\tConsole.WriteLine(text);\n}\n```\n\nGets you this:\n\n![netshell](https://user-images.githubusercontent.com/2375486/75217204-57feb580-57bc-11ea-8211-91842a631c3b.gif)\n\n\n\n## Why use netshell?\n\nnetshell was developed as a way for ops to have a simplified command-line interface into the application internals without having to know implementation details. Most of the methods you want to export are likely already written as part of tests. \n\nA great alternative for .NET applications is to use PowerShell, it allows for easy scripting of common tasks. Unfortunately, with PowerShell there are some significant hurdles:\n\n- Mix of scripts and assemblies, type loading issues\n- Async is difficult\n- Suggestions are non-trivial to implement\n- Porting existing C# code is tricky, especially when it uses [closures](https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.scriptblock.getnewclosure?redirectedfrom=MSDN\u0026view=pscore-6.2.0#System_Management_Automation_ScriptBlock_GetNewClosure)\n\n\n\n## Features \n\n* Auto-completion\n* Suggestions\n* Fuzzy matching\n* Named parameters\n* Object printer\n* Async support\n* Dependency injection\n* Help generation\n* Stacked commands\n* and more\n\n\n\n## Usage\n\n### Basics\nAdd the `Command([name], [description])` attribute to a method:\n\n```csharp\nclass Commands \n{\n    [Command(\"echo\", \"Print out the text to standard out\")]\n    void Echo(string text, ConsoleColor color = ConsoleColor.White)\n    { \n    }\n}\n```\nIn your `Main` method:\n\n```csharp\nstatic int Main(string[] args)\n {\n   var shell = new NetShell.RpcShell(new Commands()) { Prompt = \"sh\" };\n   return shell.Run();\n }\n```\nor, if you have nothing to customize:\n\n```csharp\nstatic int Main(string[] args) =\u003e NetShell.RpcShell.Run\u003cCommands\u003e();\n```\n\n### Suggestions\n\nTo create auto-complete suggestions for parameters, add a `Suggest` attribute with the name of the method that must be called to get suggestions. The method is expected to return an enumerable of strings.\n\n```csharp\n[Command(\"connect\")]\npublic void Connect(\n\t[Suggest(nameof(ListPorts))] string port = default,\n\t[Suggest(nameof(BaudRates))] int baud = 9600,            \n)\n{\n}\n\npublic string[] ListPorts() =\u003e SerialPort.GetPortNames();\npublic string[] BaudRates() =\u003e \"9600, 14400, 19200, 38400, 57600, 115200\".Split(',');\n\n```\n\n### Results\n\nYou can either choose to have a `void` method and use `Console.WriteLine`, or you can return a value from the method. Return values will be displayed with the best-matching object printer.\n\n```csharp\n[Command]\npublic Person[] GetPeople()\n{\n\treturn new Person[] { \n\t\tnew Person { Age = 10, Name = \"Asti\" }, \n\t\tnew Person { Age = 11, Name = \"Johny\" } \n\t};\n}\n```\n\nand when you run this:\n\n```\n\u003egetpeople\n ---------------\n | Age | Name  |\n ---------------\n | 10  | Asti  |\n ---------------\n | 11  | Johny |\n ---------------\n```\n\n### Dependency injection\n\nYou can do use `RpcShell.Register` to register a new dependency to be injected.\nWhenever a method is being called, it will inject all registered types as parameters, and these injected parameters will not show up as part of your command syntax.\n\nFor example, if you do\n```csharp\nshell.Register(new HttpClient());\n```\nin your method you can use `HttpClient` as a parameter, and it will be injected in.\n```csharp\n[Command(\"validate-phone\")]\npublic Task\u003cstring\u003e Validate(string number, HttpClient client) =\u003e \t\n\tclient.GetStringAsync($\"https://numvalidate.com/api/validate?number={number}\");            \n```\nThe shell itself is injected. For example, to change the current prompt from within a command:\n\n```csharp\n[Command(\"cd\")]\npublic void ChangeDir(string path, Shell shell)\n{\n\tshell.Prompt = Environment.CurrentDirectory = path;\n}\n```\n\n### Async\n\nYou can write `async` methods as you would normally. \n\n```csharp\n[Command(\"validate-phone\")]\npublic async Task\u003cstring\u003e Validate(string number)\n{\n    var response = await new HttpClient().GetAsync($\"https://numvalidate.com/api/validate?number={number}\");\n    var json = await response.Content.ReadAsStringAsync();\n    return json;\n}\n```\n\nYou can also have cancellation. \n\n```csharp\n[Command(\"validate-phone\")]\npublic async Task\u003cstring\u003e Validate(string number, CancellationToken cancellation)\n{\n    var response = await new System.Net.Http.HttpClient().GetAsync($\"https://numvalidate.com/api/validate?number={number}\", cancellation);\n    var json = await response.Content.ReadAsStringAsync();\n    return json;\n}\n```\n\nThe `CancellationToken` is injected and has no impact on your commands' syntax. See [this](https://user-images.githubusercontent.com/2375486/75220698-0824ec00-57c6-11ea-9df9-bdc11e705f85.gif).\n\nPressing any key cancels the executing command.\n\n```\n\u003e help validate-phone\nCommand validate-phone\nSyntax: validate-phone (String number)\n```\n\n### Common commands\n\nAlthough there exists a internal implementation of `help`, it's a good idea to implement your own help method with any additional info you may have.\n\n```csharp\n[Command(\"help\")]\npublic string Help(string command, RpcShell shell)\n{\n\treturn shell.GetHelp(command);\n}\n```\nThere's a default implementation for `exit`. \nImplementing `exit`:\n\n```csharp\n[Command(\"exit\")]\npublic void Exit(RpcShell shell)\n{\n\tshell.Exit(0);\n}\n```\nThere're default implementations of `help`, `exit` and `clear` in `CommandBase`.\nYou can just inherit from it if you want to avoid writing your own.\n\n## Submodules\n\nThe submodules are internal to the project to simplify differences with the original projects.\n\n- [Readline](https://github.com/cobbr/readline.git)\n- [Console Table](https://github.com/khalidabuhakmeh/ConsoleTables.git)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeviousasti%2Fnetshell","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdeviousasti%2Fnetshell","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdeviousasti%2Fnetshell/lists"}