{"id":26907319,"url":"https://github.com/thindil/nish","last_synced_at":"2025-07-23T11:04:57.090Z","repository":{"id":37380842,"uuid":"438127857","full_name":"thindil/nish","owner":"thindil","description":"Mirror of a command line shell","archived":false,"fork":false,"pushed_at":"2024-10-19T03:27:42.000Z","size":2493,"stargazers_count":29,"open_issues_count":0,"forks_count":1,"subscribers_count":5,"default_branch":"trunk","last_synced_at":"2024-10-19T07:46:20.266Z","etag":null,"topics":["command-shell","nim","shell"],"latest_commit_sha":null,"homepage":"https://www.laeran.pl.eu.org/repositories/nish/home","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thindil.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"license.txt","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},"funding":{"liberapay":"thindil","open_collective":"laeran","github":"thindil"}},"created_at":"2021-12-14T05:23:16.000Z","updated_at":"2024-10-19T03:27:46.000Z","dependencies_parsed_at":"2024-04-25T05:25:57.092Z","dependency_job_id":"8062a9c5-f3c5-44ee-b3a9-2d103f22b981","html_url":"https://github.com/thindil/nish","commit_stats":{"total_commits":2811,"total_committers":2,"mean_commits":1405.5,"dds":"0.36179295624332974","last_synced_commit":"161d88268546d9783b2c737562e9198667095c1e"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/thindil/nish","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thindil%2Fnish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thindil%2Fnish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thindil%2Fnish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thindil%2Fnish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thindil","download_url":"https://codeload.github.com/thindil/nish/tar.gz/refs/heads/trunk","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thindil%2Fnish/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266665780,"owners_count":23964971,"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","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["command-shell","nim","shell"],"created_at":"2025-04-01T11:55:52.637Z","updated_at":"2025-07-23T11:04:57.036Z","avatar_url":"https://github.com/thindil.png","language":"Nim","funding_links":["https://liberapay.com/thindil","https://opencollective.com/laeran","https://github.com/sponsors/thindil"],"categories":[],"sub_categories":[],"readme":"### General information\n\nNish is a non-POSIX, multiplatform command-line shell currently in a beta\nstage. It offers some features common for commands' shells, like Tab\ncompletion, syntax highlighting, variables, aliases. But it doesn't provide,\nfor example, own scripting language. More information about available features,\nyou can find below. If you read this file on GitHub: **please don't send pull\nrequests here**. All will be automatically closed. Any code propositions should\ngo to the [Fossil](https://www.laeran.pl/repositories/nish) repository.\n\n**IMPORTANT:** If you read the file in the project code repository: This\nversion of the file is related to the future version of the shell. It may\ncontain information not present in released versions of the program. For\nthat information, please refer to the README.md file included into the release.\n\n### Features\n\n#### Use database for store all data related to the shell\n\nAll the shell's data, configuration, history, variables and aliases are stored\nin SQLite database. It allows adding some interesting features to the shell,\nlike searching through its history.\n\n#### Global and local aliases\n\nThe shell allows declaring not only standard aliases, which are available\neverywhere, but also aliases which available only in the selected directories.\nFor example, you can declare alias `build` which in one directory will be\nexecuting `make -j5` and in another `nim release`. Aliases can be declared for\njust one directory or for each subdirectory of the selected directory too. At\nthis moment, available options for aliases are:\n\n* ID: The ID of the alias, used mostly for deleting or editing the selected\n  alias.\n* Name: The name of the alias. The text which have to be entered to execute the\n  alias. It doesn't need to be unique, but if two aliases in the same directory\n  have the same name, then the first one will be executed. The name can contain\n  only letters, numbers, and underscores.\n* Path: The main directory in which the alias works. It must be an existing\n  directory.\n* Recursive: If set to 1, the alias is available for all subdirectories of the\n  path. If set to 0, is available only in the selected directory.\n* Commands: The list of commands which will be executed as alias. The alias can\n  execute a few commands, but then, each entry on the list have to be separated\n  with new line.\n* Description: The alias description. Showed on the aliases list.\n* Output: Where to redirect the output of the commands executed by the alias.\n  By default, or if this option set to `stdout`, the output not redirected\n  at all. If set to `stderr`, then the standard output redirected to the\n  standard error. When set to any other value, it is the path (relative or\n  absolute) to the file to which the output will be saved. If the file exists,\n  the output will be added to its content. **IMPORTANT:** only default setting\n  allows interacting with the commands executed by the alias. Any other setting\n  allows only read without any ability to pass any input to the executed\n  commands.\n\nFor example, the definition of the alias can look that:\n\n\n    ID: 1\n    Name: mc\n    Path: /\n    Recursive: 1\n    Commands: mc --nosubshell\n    Description: Run MC without subshell\n    Output: stdout\n\nThe alias will be executed when the user enters `mc` in the shell. The alias is\nthe global alias, it is available for the main directory `/` and all\nsubdirectories. It executes command `mc --nosubshell`. The output of the alias\nwill be as default, nothing is redirected.\n\nThe definition of the local alias can look that:\n\n    ID: 2\n    Name: listdocs\n    Path: /home/user\n    Recursive: 0\n    Commands: cd docs \u0026\u0026 ls -lh\n    Description: Enter docs directory and list all files\n    Output: result.txt\n\nThe alias will be executed when the user enters `listdocs` in the shell in the\nhome directory. It doesn't work in any of its subdirectory. It enters `docs`\ndirectory and then runs the command `ls -lh`. If the next command should be\nexecuted only when the previous command was successful, use `\u0026\u0026` to merge them.\nIf the next command should be executed only when the previous failed, use `||`\nto merge them. The output of the alias will be redirected to the file\n`result.txt` which will be located in the same directory where the alias was\nexecuted.\n\nYou can also pass arguments to the commands of the alias. The substitutes for\narguments are start with `$` and have numbers from 1 to 9. Example: `$1`, `$5`.\nThe definition of alias which uses arguments can look that:\n\n    ID: 3\n    Name: fossopen\n    Path: /home/user/Projects\n    Recursive: 0\n    Commands: fossil open fossil/$1.fossil --workdir $1\n    Description: Open fossil repo. Required parameter is the name of fossil repo.\n    Output: stderr\n\nThe alias will be executed when the user enters `fossopen [reponame]` in the\nshell. If the user enters only `fossopen` the shell will report a problem. The\nalias is the local alias, which means it doesn't work in subdirectories. It\nruns command `fossil open fossil/[reponame].fossil --workdir [reponame]`. For\nexample, entering the shell's command: `fossopen myrepo` will execute command:\n`fossil open fossil/myrepo.fossil --workdir myrepo`. The output of the command\nwill be redirected to the standard error.\n\nThere is also special argument `$0` which mean all remaining arguments entered\nby the user. The definition of alias which uses that argument can look that:\n\n    ID: 4\n    Name: foss\n    Path: /\n    Recursive: 1\n    Commands: fossil $0\n    Description: Alias for command fossil.\n    Output: stdout\n\nThe alias will be executed when the user enters `foss` or `foss [arguments]` in\nthe shell. For example, entering the shell's command: `foss help` will execute\ncommand: `fossil help`. The output of the alias will not be redirected.\n\n#### Advanced shell's commands' history\n\nThere are available a few commands to manipulate the shell's commands' history\nlike show history or clear it. It is also possible to set the amount of\ncommands to store in the shell's history or the shell should store also invalid\ncommands or not.\n\nWhen there is some text entered by the user, the history search only commands\nwhich starts with the entered text.\n\nThe shell sorts the commands' history not only by most recently used but also by\nmost frequently used. Additionally, the command allows selecting the amount of\ncommands to show, their sorting order and criteria. These settings cam be set\nas permanent in the shell's options or ad hoc for the one time.\n\nIt is also possible to search for a command in the history with the separated\nshell command.\n\n#### Advanced shell's configuration\n\nAll shell's options can be previewed from the shell. Additionally, it is\npossible to set them inside the shell and reset options' values to the default\nvalues. Also, there are options which are read-only, like for example, the\ncurrent version of the shell's database schema.\n\n#### Global and local environment variables\n\nBeside standard support for environment variables, with `set` and `unset`\ncommands, the shell also offers ability to set environment variables only for\nthe selected directories, in the same way how aliases set. At this moment,\navailable options for variables are:\n\n* ID: The ID of the variable, used mostly for deleting or editing the selected\n  variable\n* Name: The name of the variable. It doesn't need to be unique, but if two\n  variables in the same directory have the same name, then the last one value\n  will be set as current value of the variable.\n* Path: The main directory in which the variable set.\n* Recursive: If set to 1, the variable is available for all subdirectories of\n  the path. If set to 0, is available only in the selected directory.\n* Type: The type of the variable's value. Determines what kind of values are\n  acceptable for the variable. Currently, three types of variables are available.\n  `text`: anything, `number`: any number, `path`: a valid path.\n* Value: The value of the variable.\n* Description: The variable description. Showed on the variables list.\n\nFor example, the definition of the variable can look that:\n\n\n    ID: 1\n    Name: MY_VAR\n    Path: /\n    Recursive: 1\n    Type: text\n    Value: someval\n    Description: Test variable\n\nThe definition of the local variable can look that:\n\n    ID: 2\n    Name: MY_VAR2\n    Path: /home/user\n    Recursive: 0\n    Type: number\n    Value: 12\n    Description: The second test variable\n\nThe variable will be available only in the user's home directory. It doesn't\nwork in any of its subdirectory.\n\n**IMPORTANT:** Commands `set` and `unset` doesn't work with the shell's\nspecific environment variables presented above. They work only with the\nstandard environment variables. To manage the shell's specific environment\nvariables use subcommands of the `variable` command.\n\n#### Setting the shell's prompt\n\nThe shell's prompt can be set to the output of the selected program or script.\nTo do this, set the value of the shell's option `promptCommand` to the command\nline with the desired program or script and its arguments. For example, to set\nprompt to show the current date, use command `options set promptCommand date`.\nIf you want to reset the prompt to the original state, reset its value with\ncommand `options reset promptCommand`.\n\n**ATTENTION:** the command set as the shell's option `promptCommand` will be\nexecuted every time before you execute your command. Thus, be sure it isn't too\nheavy for your system, or it isn't dangerous, for example, it doesn't steal\ncredentials, harm your system, etc.\n\n#### Plugins\n\nThe shell's offers a very simple API which allows writing its plugins in any\nprogramming language. The communication between the shell and the plugin are\nmade by standard input and output, where the API calls are sending as command\nline arguments. All arguments for the calls should be enclosed in quotes if\nthey contain spaces. The plugin's system will probably change over time\nespecially by adding new API calls. The plugins can reside in any location.\nThe directory `tools` contains the example plugin `testplugin.sh` written in\nBash.\n\nThe current version of API: **0.2**\nThe minimum required version of API for plugins to work: **0.2**\n\nAt this moment, available API calls from the shell:\n\n* `install`: called during installation of the plugin (adding it to the\n  shell).\n* `uninstall`: called during removing of the plugin from the shell.\n* `enable`: called during enabling the plugin.\n* `disable`: called during disabling the plugin.\n* `init`: called during initialization (starting) of the shell.\n* `info`: called during showing information about the plugin. Requested\n  response from the plugin should have form:\n  `answer [name of the plugin;description of the plugin;API version of the plugin;list of API used (separated by comma)]`.\n  This call is required for all plugins to work. If a plugin doesn't have it,\n  it won't be added or enabled in the shell.\n* `preCommand [command]`: called before the user's command will be executed.\n  Command argument is the name of command and all its arguments entered by the\n  user.\n* `postCommand [command]`: called after the user's command execution.\n  Command argument is the name of command and all its arguments entered by the\n  user.\n* `[command] [arguments]`: called when the plugin added the own or replaced one of\n  the built-in commands. Command is the name of the command which will be\n  executed, arguments are a string with arguments entered by the user.\n\n**ATTENTION:** the calls set as the `preCommand` and `postCommand` will be\nexecuted every time before and after you execute your command. Thus, be sure it\nisn't too heavy for your system, or it isn't dangerous, for example, it doesn't\nsteal credentials, harm your system, etc.\n\nIf the plugin doesn't answer on any API call from the shell, it should return\nerror code 2, so the shell will known that the API's call isn't supported by\nthe plugin.\n\nAvailable API calls from plugins:\n\n* `showError [text]`: show the text in the standard error output\n* `showOutput [text] ?color?`: show the text in the standard output. The\n  optional argument is the color of the message. Available options are:\n  fgBlack, fgRed, fgGreen, fgYellow, fgBlue, fgMagenta, fgCyan, fgWhite and\n  fgDefault\n* `setOption [option name] [option value] [option description] [option type]`:\n  set the shell's option. If the option doesn't exist, create a new with\n  selected parameters. Option type should be one of: integer (positive and\n  negative), float, boolean (true or false), historySort, natural (0 or above),\n  text, command (the value will be checked if is a valid command before added)\n* `removeOption [option name]`: remove the selected option from the shell.\n* `getOption [option name]`: get the value of the selected shell's option.\n* `answer [text]`: set the answer for the shell. At this moment, used only in\n  `info` call from the shell.\n* `addCommand [command name] ?subcommand? ?subcommand? ...`: add the new\n  command to the shell. The name must be unique. The command will not be added\n  if there is registered the shell's command with that name. If you want to\n  replace an existing command, use call `replaceCommand` (see below). Commands\n  named *exit*, *set*, *unset* and *cd* can't be added. Optional arguments subcommand\n  are names of the command's subcommands used in the commands' completion\n  system.\n* `deleteCommand [command name]`: remove the selected command from the shell.\n  The name must be a name of an existing shell's command.\n* `replaceCommand [command name]`: replace the selected command with code from\n  the plugin. The name must be a name of an existing shell's command.\n* `addHelp [topic] [usage] [help content]`: add the new help entry to the\n  shell. The topic must be unique. The help entry will not be added if there is\n  one with that topic. If you want to replace an existing help entry, use call\n  `updateHelp` (see below).\n* `deleteHelp [topic]`: delete the help entry with the selected topic. The\n  topic must be the topic of an existing help entry.\n* `updateHelp [topic] [usage] [help content]`: update the existing help entry\n  with the new values. The topic must be a topic of an existing help entry.\n\n#### Advanced help system\n\nThe whole content of the help is added to the local database of the shell. It\nallows searching for help topics, but also to locally modify the help entries.\nThe use can in any moment bring back the default content, or update the local\nwith the new version, with the one command.\n\nThe content of the help is located in file *help/help.cfg*. Each entry has the\nfollowing scheme:\n\n    [PluginPathOrModuleName]\n    topic=\"The help topic, used to show the help entry\"\n    usage=\"The shell's command related to the help topic\"\n    content=\"The content of the help entry\"\n\nThe help system offers some basic text formatting features. Enclosing a text\nwith some characters will change the color of the text. Most formatting\nworks only in `content` setting.\n\n* `?` will change color to blue. Works in `usage` setting too. For\n  example: `?all?`\n* `[]` will change color to cyan. Works in `usage` setting too. For\n  example: `[name]`\n* `_` will change color to yellow. For example: `_true_`.\n* ```` will change color to green. For example: ``command``.\n\n#### Tab completion\n\nThe shell offers the Tab completion for the user's entered commands with names\nof files and directories relative to the current directory and with available\ncommands. It also allows selecting a completion from the list if there is more\nthan one completion available.\n\nIt is possible to set the amount of the completions displayed on the list in\nthe shell's options.\n\nAdditionally, the shell offers the Tab completion for arguments of commands.\nBy default, the completion offers only names of directories and files as the\ncompletion. Changing its setting is possible in two ways:\n\n1. Manually\n\n    By using command `completion add` to add a new completion or `completion edit [id]`\nto edit an existing one, where *ID* is an ID of the completion to edit. You will\nbe asked for several things during setting, like the name of the command and\ntype of its parameters. It is possible to limit parameters only to directories\nor even disable the completion completely. If you select *custom* type of the\ncompletion, you will be also asked for the accepted values for the completion.\n\n2. Importing from a file\n\n    It is possible to import a completion from a file, previously generated with\nthe command `completion export [id] [filename]` where *filename* is the name of the\nfile to which the completion will be exported and *ID* is an ID of the completion to\nexport. To import that completion, use the command `completion import [filename]`\nwhere *filename* is the name of the file to import.\n\nCommand `completion export [id] [filename]` exports the selected completion as\na configuration file. It contains fields:\n\n* `Command`: the command for which the completion is.\n* `Type`: the type of completion. Can be: *Directories only*, *Files only*,\n  *Directories and files*, *Commands*, *Custom* or *Completion for the selected\n  command should be disabled*.\n* `Values`: the values available for the completion. It is needed only for\n  *Custom* type of the completion. All values must be separated by semicolon\n  and in quotes.\n\nFor example, the file with an exported completion can look that:\n\n    Command=ls\n    Type=Custom\n    Values=\"te;ew;wr\"\n\nCommand `completion` allows managing the Tab completions for commands, like\ndeleting them, previewing or listing all of them. For more information about\nthe command and its subcommands, please look at the corresponding shell's help\nentries.\n\n#### Other features\n\n* Coloring the user entered command on green when it is valid or red when it is\n  invalid, separated colors for environment variables and commands' arguments\n  which contains quotes or double quotes. Can be enabled or disabled in the\n  shell's options.\n* Suggestions for commands when the user entered an unknown command. It is\n  possible to set the precision of the suggestions with the shell's option. The\n  feature can be disabled either.\n* Setting the terminal title, can be enabled or disabled in the shell's options.\n* Theming system. It is possible to set the colors and style, like use\n  underline, bold or italic font (if the terminal emulator supports it) for\n  various of the shell's outputs (errors, help entries, etc.).\n* Ability to execute command with or without the system's default shell.\n  Additionally, the default behavior of the shell can be set in the shell's\n  options.\n\n### How to install\n\n#### Precompiled packages\n\nThere are available binary packages for Linux and FreeBSD 64-bit both on the\ndownload page. If you want to use Nish on different platform, you have to build\nit from the source.\n\n#### Build from the source\n\nYou will need:\n\n* [Nim compiler](https://nim-lang.org/install.html)\n* [Contracts](https://github.com/Udiknedormin/NimContracts)\n* [Nimassets](https://github.com/xmonader/nimassets)\n* [TermStyle](https://github.com/PMunch/termstyle)\n* [Nancy](https://github.com/PMunch/nancy)\n* [Nimalyzer](https://github.com/thindil/nimalyzer)\n* [Norm](https://github.com/moigagoo/norm)\n* [Unittests2](https://github.com/status-im/nim-unittest2)\n\nYou can install them manually or by using [Nimble](https://github.com/nim-lang/nimble).\nIn that second option, type `nimble install https://github.com/thindil/nish` to\ninstall the shell and all dependencies. Generally it is recommended to use\n`nimble release` to build the project in release (optimized) mode or\n`nimble debug` to build it in the debug mode.\n\n### Design goals\n\n* Provide sane defaults: even if command shells are for power users, it doesn't\n  mean that their time isn't valuable. Provide good default settings for the\n  new installation of the shell.\n* A simple, extendable core: the base shell should be small as possible,\n  contains only things useful for everyone. The rest of functionality should be\n  in the shell's plugins.\n* Configure not rule: add an ability to configure, enable or disable almost\n  everything: style, commands, functionality.\n* Safety first: prioritize the safety and security over new features or even\n  speed. A broken program is less useful than the working simple one.\n* KISS: Keep It Simple Stupid: when looking for a solution of a problem, use the\n  simplest approach. After all the code have been maintained for some time.\n\n### License\n\nThe project released under 3-Clause BSD license.\n\n---\nThat's all for now, as usual, I have probably forgotten about something important ;)\n\nBartek thindil Jasicki\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthindil%2Fnish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthindil%2Fnish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthindil%2Fnish/lists"}